
Discord Notify
- 9 installs
- Updated August 4, 2026
- 958877748/skills
discord-notify is a Claude Code skill that sends a real-time notification to a user's phone via a Discord bot.
About
discord-notify is a Claude Code skill that sends a real-time notification to the user's phone through a Discord bot. It ships a check.js environment validator and a send.js sender that splits messages longer than 2000 characters. A developer uses it when they want the agent to ping them once a long task finishes, a monitored condition is met, or an error occurs.
- Sends a real-time notification to the user's phone through a Discord bot
- Includes an environment check script and auto-splits messages over 2000 characters
- Triggers when the user asks to be notified on task completion, a condition, or an error
Discord Notify by the numbers
- 9 all-time installs (skills.sh)
- Ranked #1,495 of 2,715 Automation & Workflows skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
discord-notify capabilities & compatibility
Free; requires a Discord bot token and user ID set as DISCORD_BOT_TOKEN and DISCORD_USER_ID env vars.
- Capabilities
- send notification · phone alert · task completion alert
- Works with
- slack
- Use cases
- orchestration
- Pricing
- Bring your own API key
What discord-notify says it does
通过 Discord 向用户手机发送实时通知。
**支持超长消息**:超过 2000 字符会自动分割发送。
npx skills add https://github.com/958877748/skills --skill discord-notifyAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 9 |
|---|---|
| Last updated | August 4, 2026 |
| Repository | 958877748/skills ↗ |
What it does
Send a Discord direct-message notification to the user's phone when a task completes or a condition is met.
When should I use this skill?
The user asks to be notified on their phone when a task finishes, a condition is reached, or an error occurs.
What you get
Sends a Discord message to the user's phone on completion, a status change, or an error, splitting long messages automatically.
By the numbers
- messages over 2000 characters auto-split into multiple sends
Files
discord-notify
通过 Discord 向用户手机发送实时通知。
When to use
当用户表达以下意图时,使用此 Skill:
- "完成后通知我"
- "有结果了发消息给我"
- "帮我监控这个,有问题告诉我"
- "跑完了告诉我一声"
- "达成 xxx 条件后通知我"
- "发个提醒/通知到我手机"
典型场景:
- 🔔 任务完成通知(脚本跑完、构建完成等)
- 📊 状态监控(网站恢复、服务异常等)
- ⏰ 定时提醒(到点提醒我 xxx)
- 📋 结果汇报(数据处理完了告诉你)
环境检测
首次使用时,AI 应运行检测脚本检查环境配置:
cd discord-notify && node check.js检测脚本会检查:
- ✅ 环境变量是否配置
- ✅ 依赖是否安装
- ✅ Bot Token 是否有效
- ✅ User ID 是否有效
根据检测结果,AI 应指导用户完成配置。
发送通知
node discord-notify/send.js "通知内容"支持超长消息:超过 2000 字符会自动分割发送。
环境变量
| 变量 | 必填 | 说明 |
|---|---|---|
DISCORD_BOT_TOKEN | ✅ | 机器人 Token |
DISCORD_USER_ID | ✅ | 目标用户 ID |
HTTPS_PROXY / HTTP_PROXY / ALL_PROXY | ❌ | 代理地址(可选) |
User ID 获取方式
Discord 设置 → 高级 → 开启开发者模式 → 右键自己 → 复制 ID
配置步骤
1. 创建 Discord Bot
- 访问 https://discord.com/developers/applications
- 创建 Application → Bot → 复制 Token
2. 邀请 Bot 到服务器
- 使用 Bot 的 OAuth2 URL 邀请到你的 Discord 服务器
3. 获取 User ID
- Discord 设置 → 高级 → 开启开发者模式
- 右键点击你的头像 → 复制 ID
4. 配置环境变量
export DISCORD_BOT_TOKEN="你的Token"
export DISCORD_USER_ID="你的ID"
export HTTPS_PROXY="http://127.0.0.1:1080" # 可选返回值
成功
{
"success": true,
"message": "消息发送成功",
"chunks": 1,
"sent": 1
}超长消息会显示分割信息:
{
"success": true,
"message": "消息发送成功",
"chunks": 2,
"sent": 2,
"note": "消息已分割为 2 条发送"
}失败
{
"success": false,
"error": "无法创建私聊频道: 请求参数错误: Invalid Recipient(s)"
}AI 使用示例
当用户说:"帮我跑这个脚本,跑完了告诉我"
AI 应该: 1. 开始执行脚本 2. 等待完成 3. 调用 node discord-notify/send.js "✅ 脚本执行完成!" 4. 告诉用户"已通知"
目录结构
discord-notify/
├── SKILL.md # Skill 说明文档
├── check.js # 环境检测脚本
├── send.js # 发送通知脚本
└── package.json # 依赖配置node_modules/
package-lock.json
#!/usr/bin/env node
/**
* discord-notify 环境检测脚本
*
* 运行此脚本检查当前环境是否配置正确
* AI 可以通过此脚本的输出了解如何配置此 skill
*/
const fetch = require('node-fetch');
const HttpsProxyAgent = require('https-proxy-agent');
const fs = require('fs');
const path = require('path');
// 颜色输出
const colors = {
green: '\x1b[32m',
red: '\x1b[31m',
yellow: '\x1b[33m',
cyan: '\x1b[36m',
reset: '\x1b[0m'
};
const pass = (msg) => console.log(`${colors.green}✅ ${msg}${colors.reset}`);
const fail = (msg) => console.log(`${colors.red}❌ ${msg}${colors.reset}`);
const warn = (msg) => console.log(`${colors.yellow}⚠️ ${msg}${colors.reset}`);
const info = (msg) => console.log(`${colors.cyan}ℹ️ ${msg}${colors.reset}`);
// 检测结果
const results = {
ready: false,
checks: [],
missing: [],
env: {}
};
/**
* 检查环境变量
*/
function checkEnv() {
console.log('\n📋 检查环境变量...\n');
// BOT_TOKEN
const botToken = process.env.DISCORD_BOT_TOKEN;
if (botToken) {
pass('DISCORD_BOT_TOKEN 已配置');
results.env.DISCORD_BOT_TOKEN = '已设置';
} else {
fail('DISCORD_BOT_TOKEN 未配置');
results.missing.push('DISCORD_BOT_TOKEN');
}
// USER_ID
const userId = process.env.DISCORD_USER_ID;
if (userId) {
pass('DISCORD_USER_ID 已配置');
results.env.DISCORD_USER_ID = '已设置';
} else {
fail('DISCORD_USER_ID 未配置');
results.missing.push('DISCORD_USER_ID');
}
// PROXY(可选)
const proxy = process.env.HTTPS_PROXY || process.env.HTTP_PROXY || process.env.ALL_PROXY;
if (proxy) {
info(`代理已配置: ${proxy}`);
results.env.PROXY = proxy;
} else {
warn('未配置代理(如需代理请设置 HTTPS_PROXY)');
}
}
/**
* 检查依赖
*/
function checkDeps() {
console.log('\n📦 检查依赖...\n');
try {
require('node-fetch');
pass('node-fetch 已安装');
} catch {
fail('node-fetch 未安装');
results.missing.push('npm install');
}
try {
require('https-proxy-agent');
pass('https-proxy-agent 已安装');
} catch {
fail('https-proxy-agent 未安装');
results.missing.push('npm install');
}
}
/**
* 测试 Discord API 连接
*/
async function testApi() {
console.log('\n🔌 测试 Discord API 连接...\n');
const botToken = process.env.DISCORD_BOT_TOKEN;
if (!botToken) {
warn('跳过 API 测试(BOT_TOKEN 未配置)');
return;
}
const headers = {
'Authorization': `Bot ${botToken}`
};
const proxy = process.env.HTTPS_PROXY || process.env.HTTP_PROXY || process.env.ALL_PROXY;
const fetchOptions = proxy ? { agent: new HttpsProxyAgent(proxy) } : {};
try {
const res = await fetch('https://discord.com/api/v10/users/@me', {
headers,
...fetchOptions
});
if (res.ok) {
const bot = await res.json();
pass(`Bot 连接成功: ${bot.username}#${bot.discriminator || '0'}`);
results.env.BOT_NAME = bot.username;
} else if (res.status === 401) {
fail('Bot Token 无效,请检查 Token 是否正确');
} else {
const body = await res.text();
fail(`API 返回错误: HTTP ${res.status}`);
results.checks.push({ name: 'API', status: 'error', message: body });
}
} catch (err) {
fail(`无法连接 Discord API: ${err.message}`);
if (proxy) {
info('请检查代理配置是否正确');
} else {
info('如在中国大陆,可能需要配置代理');
}
}
}
/**
* 验证 User ID 是否有效
* 通过创建 DM 频道来验证(不会发送消息)
*/
async function testUserId() {
console.log('\n👤 验证 User ID...\n');
const botToken = process.env.DISCORD_BOT_TOKEN;
const userId = process.env.DISCORD_USER_ID;
if (!botToken || !userId) {
warn('跳过 User ID 验证(环境变量未配置)');
return;
}
const headers = {
'Authorization': `Bot ${botToken}`,
'Content-Type': 'application/json'
};
const proxy = process.env.HTTPS_PROXY || process.env.HTTP_PROXY || process.env.ALL_PROXY;
const agent = proxy ? new HttpsProxyAgent(proxy) : undefined;
const fetchOptions = agent ? { agent } : {};
try {
const dmRes = await fetch('https://discord.com/api/v10/users/@me/channels', {
method: 'POST',
headers,
body: JSON.stringify({ recipient_id: userId }),
...fetchOptions
});
if (dmRes.ok) {
const dm = await dmRes.json();
pass(`User ID 有效,DM 频道 ID: ${dm.id}`);
results.env.DM_CHANNEL_ID = dm.id;
} else if (dmRes.status === 400) {
fail('User ID 无效或用户不存在');
results.missing.push('DISCORD_USER_ID (无效)');
} else {
const body = await dmRes.text();
fail(`验证失败: HTTP ${dmRes.status}`);
}
} catch (err) {
fail(`验证失败: ${err.message}`);
}
}
/**
* 输出配置指引
*/
function printGuide() {
console.log('\n' + '='.repeat(50));
console.log('📚 配置指引');
console.log('='.repeat(50));
if (results.missing.length === 0) {
console.log('\n🎉 环境配置完整,discord-notify 可以正常使用!\n');
console.log('使用方法:');
console.log(' node send.js "你的消息内容"\n');
results.ready = true;
} else {
console.log('\n⚠️ 以下项目需要配置:\n');
if (results.missing.includes('DISCORD_BOT_TOKEN')) {
console.log('1️⃣ 获取 Discord Bot Token:');
console.log(' - 访问 https://discord.com/developers/applications');
console.log(' - 创建 Application → Bot → 复制 Token\n');
}
if (results.missing.includes('DISCORD_USER_ID')) {
console.log('2️⃣ 获取你的 Discord User ID:');
console.log(' - Discord 设置 → 高级 → 开启开发者模式');
console.log(' - 右键点击你的头像 → 复制 ID\n');
}
if (results.missing.includes('npm install')) {
console.log('3️⃣ 安装依赖:');
console.log(' - 运行: npm install\n');
}
console.log('4️⃣ 配置环境变量(在 ~/.bashrc 或 ~/.zshrc 中添加):');
console.log(' export DISCORD_BOT_TOKEN="你的Token"');
console.log(' export DISCORD_USER_ID="你的ID"');
console.log(' export HTTPS_PROXY="http://127.0.0.1:1080" # 可选,如需代理\n');
}
}
/**
* 输出机器可读的 JSON 结果
*/
function printJsonResult() {
const output = {
ready: results.ready,
missing: results.missing,
env: results.env,
message: results.ready
? 'discord-notify 已就绪,可以使用'
: 'discord-notify 需要配置后才能使用'
};
console.log('\n📊 检测结果 (JSON):');
console.log(JSON.stringify(output, null, 2));
}
/**
* 主函数
*/
async function main() {
console.log('='.repeat(50));
console.log('🔍 discord-notify 环境检测');
console.log('='.repeat(50));
checkEnv();
checkDeps();
await testApi();
await testUserId();
printGuide();
printJsonResult();
}
main().catch(err => {
console.error('\n❌ 检测脚本执行出错:', err.message);
process.exit(1);
});
{
"name": "discord-notify",
"version": "1.0.0",
"main": "send.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"https-proxy-agent": "^5.0.1",
"node-fetch": "^2.7.0"
}
}
#!/usr/bin/env node
const fetch = require('node-fetch');
const HttpsProxyAgent = require('https-proxy-agent');
// Discord 消息长度限制
const MAX_MESSAGE_LENGTH = 2000;
// 配置
const BOT_TOKEN = process.env.DISCORD_BOT_TOKEN;
const USER_ID = process.env.DISCORD_USER_ID;
const PROXY_URL = process.env.HTTPS_PROXY || process.env.HTTP_PROXY || process.env.ALL_PROXY;
const MESSAGE = process.argv[2];
// 参数校验
if (!BOT_TOKEN) {
console.error('❌ 错误: 未设置 DISCORD_BOT_TOKEN 环境变量');
process.exit(1);
}
if (!USER_ID) {
console.error('❌ 错误: 未设置 DISCORD_USER_ID 环境变量');
process.exit(1);
}
if (!MESSAGE) {
console.error('用法: node send.js "消息内容"');
console.error('示例: node send.js "Hello, Discord!"');
process.exit(1);
}
/**
* 带代理的 fetch 请求
* 优先直连,失败后尝试代理
*/
async function fetchWithProxy(url, options = {}) {
// 先尝试直连
try {
const res = await fetch(url, options);
if (res.ok) return res;
// 直连失败且有代理配置,尝试代理
if (PROXY_URL) {
return await fetchWithProxyVia(url, options, PROXY_URL);
}
// 没有代理,返回原响应让调用方处理错误
return res;
} catch (err) {
// 网络错误,尝试代理
if (PROXY_URL) {
return await fetchWithProxyVia(url, options, PROXY_URL);
}
throw err;
}
}
/**
* 通过代理发送请求
*/
async function fetchWithProxyVia(url, options, proxyUrl) {
const agent = new HttpsProxyAgent(proxyUrl);
return fetch(url, { ...options, agent });
}
/**
* 解析 Discord API 错误,返回友好提示
*/
function parseDiscordError(status, body) {
const errorMessages = {
400: '请求参数错误',
401: 'Bot Token 无效或已过期',
403: 'Bot 没有权限执行此操作',
404: '用户不存在或无法找到',
429: '请求过于频繁,请稍后重试',
500: 'Discord 服务器内部错误',
503: 'Discord 服务暂时不可用'
};
const friendlyMsg = errorMessages[status] || `未知错误 (HTTP ${status})`;
// 尝试解析 Discord 错误详情
try {
const error = JSON.parse(body);
if (error.message) {
return `${friendlyMsg}: ${error.message}`;
}
} catch {}
return friendlyMsg;
}
/**
* 将长消息分割成多个片段
* 智能分割:优先在换行符处分割,其次在空格处
*/
function splitMessage(text, maxLength = MAX_MESSAGE_LENGTH) {
if (text.length <= maxLength) {
return [text];
}
const chunks = [];
let remaining = text;
while (remaining.length > 0) {
if (remaining.length <= maxLength) {
chunks.push(remaining);
break;
}
// 在限制范围内寻找最佳分割点
let splitIndex = maxLength;
// 优先在换行符处分割
const lastNewline = remaining.lastIndexOf('\n', maxLength - 1);
if (lastNewline > maxLength * 0.5) {
splitIndex = lastNewline + 1;
} else {
// 其次在空格处分割
const lastSpace = remaining.lastIndexOf(' ', maxLength - 1);
if (lastSpace > maxLength * 0.5) {
splitIndex = lastSpace + 1;
}
}
chunks.push(remaining.slice(0, splitIndex));
remaining = remaining.slice(splitIndex);
}
return chunks;
}
/**
* 发送单条消息
*/
async function sendMessage(channelId, content) {
const headers = {
'Authorization': `Bot ${BOT_TOKEN}`,
'Content-Type': 'application/json'
};
const res = await fetchWithProxy(
`https://discord.com/api/v10/channels/${channelId}/messages`,
{
method: 'POST',
headers,
body: JSON.stringify({ content })
}
);
if (!res.ok) {
const body = await res.text();
const errorMsg = parseDiscordError(res.status, body);
throw new Error(`发送消息失败: ${errorMsg}`);
}
return res.json();
}
/**
* 主函数:发送 DM 消息
*/
async function sendDM() {
const headers = {
'Authorization': `Bot ${BOT_TOKEN}`,
'Content-Type': 'application/json'
};
// 1. 创建 DM 频道
const dmRes = await fetchWithProxy(
'https://discord.com/api/v10/users/@me/channels',
{
method: 'POST',
headers,
body: JSON.stringify({ recipient_id: USER_ID })
}
);
if (!dmRes.ok) {
const body = await dmRes.text();
const errorMsg = parseDiscordError(dmRes.status, body);
throw new Error(`无法创建私聊频道: ${errorMsg}`);
}
const dmChannel = await dmRes.json();
// 2. 分割消息并发送
const chunks = splitMessage(MESSAGE);
let sentCount = 0;
for (const chunk of chunks) {
await sendMessage(dmChannel.id, chunk);
sentCount++;
}
// 3. 返回结果
const result = {
success: true,
message: '消息发送成功',
chunks: chunks.length,
sent: sentCount
};
if (chunks.length > 1) {
result.note = `消息已分割为 ${chunks.length} 条发送`;
}
console.log(JSON.stringify(result));
}
// 执行
sendDM().catch(err => {
console.error(JSON.stringify({
success: false,
error: err.message
}));
process.exit(1);
});
Related skills
FAQ
What credentials does discord-notify need?
It needs DISCORD_BOT_TOKEN and DISCORD_USER_ID environment variables, plus optional HTTP(S) proxy variables.
Does it handle long messages?
Yes, messages over 2000 characters are automatically split and sent as multiple Discord messages.