@hoverlover/cc-discord 0.2.1 → 0.2.3
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.
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: send-imessage
|
|
3
|
+
description: Use when the user asks to "send a text", "send an iMessage", "text someone", "send a message to [phone number]", "message [person]", or discusses sending SMS/iMessage. Also use when scheduling text messages or automating iMessage delivery.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Send iMessage
|
|
7
|
+
|
|
8
|
+
Send text messages via macOS Messages.app using the `send-imessage` CLI tool. This skill enables sending iMessages and SMS directly from the Mac.
|
|
9
|
+
|
|
10
|
+
## When This Skill Applies
|
|
11
|
+
|
|
12
|
+
- User asks to send a text message or iMessage
|
|
13
|
+
- User asks to text someone (by name, phone number, or Apple ID)
|
|
14
|
+
- User wants to schedule or automate text message delivery
|
|
15
|
+
- User asks about messaging capabilities
|
|
16
|
+
|
|
17
|
+
## Tool Usage
|
|
18
|
+
|
|
19
|
+
The `send-imessage` tool is available as a Bash command:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
send-imessage --to "<recipient>" "<message>"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Parameters
|
|
26
|
+
|
|
27
|
+
| Flag | Required | Description |
|
|
28
|
+
|------|----------|-------------|
|
|
29
|
+
| `--to` | Yes | Phone number (10-digit US or with +1) or Apple ID email |
|
|
30
|
+
| `--sms` | No | Force SMS delivery instead of iMessage |
|
|
31
|
+
| `"message"` | Yes | The message text (positional argument) |
|
|
32
|
+
|
|
33
|
+
### Examples
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Send to a US phone number (auto-normalizes to +1)
|
|
37
|
+
send-imessage --to "4175551234" "Hey, just checking in!"
|
|
38
|
+
|
|
39
|
+
# Send to a number with country code
|
|
40
|
+
send-imessage --to "+14175551234" "Meeting at 3pm"
|
|
41
|
+
|
|
42
|
+
# Send to an Apple ID email
|
|
43
|
+
send-imessage --to "user@icloud.com" "Hello from Alfred!"
|
|
44
|
+
|
|
45
|
+
# Force SMS instead of iMessage
|
|
46
|
+
send-imessage --to "4175551234" --sms "This is an SMS"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Phone Number Handling
|
|
50
|
+
|
|
51
|
+
The tool auto-normalizes US phone numbers:
|
|
52
|
+
- `4175551234` (10 digits) becomes `+14175551234`
|
|
53
|
+
- `14175551234` (11 digits) becomes `+14175551234`
|
|
54
|
+
- `+14175551234` stays as-is
|
|
55
|
+
- International numbers should include the `+` prefix
|
|
56
|
+
|
|
57
|
+
## Important Notes
|
|
58
|
+
|
|
59
|
+
- **macOS only**: This tool uses AppleScript and requires macOS with Messages.app
|
|
60
|
+
- **Apple ID required**: The Mac must be signed into an Apple ID with iMessage enabled
|
|
61
|
+
- **First-run permissions**: macOS may prompt for automation permissions the first time
|
|
62
|
+
- **Delivery**: iMessage is used by default; use `--sms` flag to force SMS
|
|
63
|
+
- **No read receipts**: The tool can only send, not read incoming messages
|
|
64
|
+
- **Rate limiting**: Avoid sending many messages in rapid succession to prevent Apple throttling
|
|
65
|
+
|
|
66
|
+
## Error Handling
|
|
67
|
+
|
|
68
|
+
If the send fails:
|
|
69
|
+
1. Check that Messages.app is running and signed in
|
|
70
|
+
2. Verify the recipient phone number or Apple ID is correct
|
|
71
|
+
3. Check that macOS automation permissions are granted for the terminal/process
|
|
72
|
+
4. Try the `--sms` flag if iMessage delivery fails
|
|
73
|
+
|
|
74
|
+
## Combining with Scheduling
|
|
75
|
+
|
|
76
|
+
Use cron or systemd timers to schedule messages:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Example: send a daily 9am reminder
|
|
80
|
+
# crontab entry:
|
|
81
|
+
# 0 9 * * * /path/to/tools/send-imessage --to "4175551234" "Good morning! Don't forget your standup."
|
|
82
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hoverlover/cc-discord",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Discord <-> Claude Code relay: use your Claude subscription to power per-channel AI bots",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"prompts/",
|
|
15
15
|
"memory/",
|
|
16
16
|
".claude/settings.template.json",
|
|
17
|
+
".claude/skills/",
|
|
17
18
|
".env.example",
|
|
18
19
|
".env.relay.example",
|
|
19
20
|
".env.worker.example"
|
package/scripts/channel-agent.sh
CHANGED
|
@@ -88,6 +88,41 @@ export AGENT_ID="$CHANNEL_ID"
|
|
|
88
88
|
export CLAUDE_AGENT_ID="${CLAUDE_AGENT_ID:-claude-discord}"
|
|
89
89
|
export CLAUDE_RUNTIME_ID="${CLAUDE_RUNTIME_ID:-rt_$(date +%s)_${RANDOM}}"
|
|
90
90
|
|
|
91
|
+
# Determine Claude's project directory (where .claude/skills/ are discovered).
|
|
92
|
+
# - CC_DISCORD_HOME overrides everything
|
|
93
|
+
# - If cwd has a .claude/ directory (local dev / bun start from repo), use cwd
|
|
94
|
+
# - Otherwise default to ~/.cc-discord (bunx / installed package)
|
|
95
|
+
if [ -n "${CC_DISCORD_HOME:-}" ]; then
|
|
96
|
+
CLAUDE_PROJECT_DIR="$CC_DISCORD_HOME"
|
|
97
|
+
elif [ -d ".claude" ]; then
|
|
98
|
+
CLAUDE_PROJECT_DIR="$(pwd)"
|
|
99
|
+
else
|
|
100
|
+
CLAUDE_PROJECT_DIR="$HOME/.cc-discord"
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
mkdir -p "$CLAUDE_PROJECT_DIR/.claude/skills"
|
|
104
|
+
|
|
105
|
+
# Seed built-in skills from the package into the project directory.
|
|
106
|
+
# Only copies skills that don't already exist (user modifications are preserved).
|
|
107
|
+
if [ -d "$ROOT_DIR/.claude/skills" ] && [ "$ROOT_DIR" != "$CLAUDE_PROJECT_DIR" ]; then
|
|
108
|
+
for skill_dir in "$ROOT_DIR/.claude/skills"/*/; do
|
|
109
|
+
skill_name="$(basename "$skill_dir")"
|
|
110
|
+
if [ ! -d "$CLAUDE_PROJECT_DIR/.claude/skills/$skill_name" ]; then
|
|
111
|
+
cp -r "$skill_dir" "$CLAUDE_PROJECT_DIR/.claude/skills/$skill_name"
|
|
112
|
+
echo "[channel-agent:$CHANNEL_NAME] Seeded skill: $skill_name"
|
|
113
|
+
fi
|
|
114
|
+
done
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
# Copy settings.json into the project dir so Claude sees it as a project config.
|
|
118
|
+
if [ "$ROOT_DIR" != "$CLAUDE_PROJECT_DIR" ] && [ -f "$SETTINGS_PATH" ]; then
|
|
119
|
+
mkdir -p "$CLAUDE_PROJECT_DIR/.claude"
|
|
120
|
+
cp "$SETTINGS_PATH" "$CLAUDE_PROJECT_DIR/.claude/settings.json"
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
cd "$CLAUDE_PROJECT_DIR"
|
|
124
|
+
echo "[channel-agent:$CHANNEL_NAME] Claude project dir: $CLAUDE_PROJECT_DIR"
|
|
125
|
+
|
|
91
126
|
# Build the channel-specific system prompt
|
|
92
127
|
SYSTEM_PROMPT="$(sed \
|
|
93
128
|
-e "s|__CHANNEL_ID__|${CHANNEL_ID}|g" \
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Send an iMessage via macOS Messages.app using AppleScript.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* send-imessage --to "+14175551234" "Hello from Alfred!"
|
|
8
|
+
* send-imessage --to "+14175551234" --sms "This goes as SMS"
|
|
9
|
+
* send-imessage --to "user@icloud.com" "Hello via Apple ID"
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { $ } from "bun";
|
|
13
|
+
|
|
14
|
+
const args = process.argv.slice(2);
|
|
15
|
+
let to: string | null = null;
|
|
16
|
+
let useSms = false;
|
|
17
|
+
const textParts: string[] = [];
|
|
18
|
+
|
|
19
|
+
for (let i = 0; i < args.length; i++) {
|
|
20
|
+
const arg = args[i];
|
|
21
|
+
if (arg === "--to" && args[i + 1]) {
|
|
22
|
+
to = args[++i];
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (arg === "--sms") {
|
|
26
|
+
useSms = true;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (arg === "--help" || arg === "-h") {
|
|
30
|
+
console.log(`
|
|
31
|
+
Usage: send-imessage --to <phone_or_appleid> [--sms] "message"
|
|
32
|
+
|
|
33
|
+
Options:
|
|
34
|
+
--to Phone number (with country code, e.g. +14175551234) or Apple ID email
|
|
35
|
+
--sms Force SMS instead of iMessage (uses SMS service)
|
|
36
|
+
|
|
37
|
+
Examples:
|
|
38
|
+
send-imessage --to "+14175551234" "Hello!"
|
|
39
|
+
send-imessage --to "user@icloud.com" "Hey there"
|
|
40
|
+
send-imessage --to "+14175551234" --sms "SMS fallback"
|
|
41
|
+
`);
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
textParts.push(arg);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const message = textParts.join(" ").trim();
|
|
48
|
+
|
|
49
|
+
if (!to) {
|
|
50
|
+
console.error("Error: --to is required. Use --help for usage.");
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!message) {
|
|
55
|
+
console.error("Error: message text is required. Use --help for usage.");
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Normalize phone number: ensure it starts with +1 if it's a 10-digit US number
|
|
60
|
+
let normalizedTo = to;
|
|
61
|
+
if (/^\d{10}$/.test(to)) {
|
|
62
|
+
normalizedTo = `+1${to}`;
|
|
63
|
+
} else if (/^1\d{10}$/.test(to)) {
|
|
64
|
+
normalizedTo = `+${to}`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Escape single quotes for AppleScript
|
|
68
|
+
const escapedMessage = message.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
69
|
+
const escapedTo = normalizedTo.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
70
|
+
|
|
71
|
+
// Build AppleScript
|
|
72
|
+
const serviceFilter = useSms
|
|
73
|
+
? 'service type = SMS'
|
|
74
|
+
: 'service type = iMessage';
|
|
75
|
+
|
|
76
|
+
const script = `tell application "Messages" to send "${escapedMessage}" to buddy "${escapedTo}" of (1st service whose ${serviceFilter})`;
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
const result = await $`osascript -e ${script}`.quiet();
|
|
80
|
+
|
|
81
|
+
if (result.exitCode !== 0) {
|
|
82
|
+
const stderr = result.stderr.toString().trim();
|
|
83
|
+
console.error(`Failed to send iMessage: ${stderr}`);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log(`iMessage sent to ${normalizedTo}: "${message}"`);
|
|
88
|
+
process.exit(0);
|
|
89
|
+
} catch (err: unknown) {
|
|
90
|
+
const error = err as Error & { stderr?: Buffer };
|
|
91
|
+
const stderr = error.stderr?.toString().trim() || error.message;
|
|
92
|
+
console.error(`Failed to send iMessage: ${stderr}`);
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export {};
|