afk-code 0.1.4 → 0.2.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.md +42 -32
- package/dist/cli/index.js +34 -29
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,29 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
Monitor and interact with Claude Code sessions from Slack, Discord, or Telegram. Respond from your phone while AFK.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<img src="https://github.com/user-attachments/assets/83083b63-9ca2-4ef0-b83d-fcc51bd2fff9" alt="AFK Code iPhone Slack screenshot" width="400">
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Client Comparison
|
|
8
|
+
|
|
9
|
+
Telegram and Discord are recommended.
|
|
10
|
+
|
|
11
|
+
| | Telegram | Discord | Slack |
|
|
12
|
+
|---|---|---|---|
|
|
13
|
+
| Siri integration | Receive & Send | Receive only | Receive only |
|
|
14
|
+
| Multi-session support | One at a time (switchable) | Yes | Yes |
|
|
15
|
+
| Permissions required | Personal | Personal | Admin |
|
|
16
|
+
|
|
17
|
+
## Quick Start (Telegram)
|
|
8
18
|
|
|
9
19
|
```bash
|
|
10
|
-
# 1. Create a
|
|
11
|
-
#
|
|
20
|
+
# 1. Create a bot with @BotFather on Telegram
|
|
21
|
+
# - Send /newbot and follow the prompts
|
|
22
|
+
# - Copy the bot token
|
|
12
23
|
|
|
13
|
-
# 2.
|
|
14
|
-
# -
|
|
15
|
-
# -
|
|
16
|
-
# -
|
|
24
|
+
# 2. Get your Chat ID
|
|
25
|
+
# - Message your bot, then visit:
|
|
26
|
+
# - https://api.telegram.org/bot<TOKEN>/getUpdates
|
|
27
|
+
# - Find "chat":{"id":YOUR_CHAT_ID}
|
|
17
28
|
|
|
18
29
|
# 3. Configure and run
|
|
19
|
-
npx afk-code
|
|
20
|
-
npx afk-code
|
|
30
|
+
npx afk-code telegram setup # Enter your credentials
|
|
31
|
+
npx afk-code telegram # Start the bot
|
|
21
32
|
|
|
22
33
|
# 4. In another terminal, start a monitored Claude session
|
|
23
|
-
npx afk-code
|
|
34
|
+
npx afk-code claude
|
|
24
35
|
```
|
|
25
36
|
|
|
26
|
-
A new channel is created for each session. Messages relay bidirectionally.
|
|
27
|
-
|
|
28
37
|
## Quick Start (Discord)
|
|
29
38
|
|
|
30
39
|
```bash
|
|
@@ -42,39 +51,40 @@ npx afk-code discord setup # Enter your credentials
|
|
|
42
51
|
npx afk-code discord # Start the bot
|
|
43
52
|
|
|
44
53
|
# 4. In another terminal, start a monitored Claude session
|
|
45
|
-
npx afk-code
|
|
54
|
+
npx afk-code claude
|
|
46
55
|
```
|
|
47
56
|
|
|
48
|
-
## Quick Start (
|
|
57
|
+
## Quick Start (Slack)
|
|
49
58
|
|
|
50
59
|
```bash
|
|
51
|
-
# 1. Create a
|
|
52
|
-
#
|
|
53
|
-
# - Copy the bot token
|
|
60
|
+
# 1. Create a Slack app at https://api.slack.com/apps
|
|
61
|
+
# Click "Create New App" → "From manifest" → paste slack-manifest.json
|
|
54
62
|
|
|
55
|
-
# 2.
|
|
56
|
-
# -
|
|
57
|
-
# -
|
|
58
|
-
# -
|
|
63
|
+
# 2. Install to your workspace and get credentials:
|
|
64
|
+
# - Bot Token (xoxb-...) from OAuth & Permissions
|
|
65
|
+
# - App Token (xapp-...) from Basic Information → App-Level Tokens (needs connections:write)
|
|
66
|
+
# - Your User ID from your Slack profile → "..." → Copy member ID
|
|
59
67
|
|
|
60
68
|
# 3. Configure and run
|
|
61
|
-
npx afk-code
|
|
62
|
-
npx afk-code
|
|
69
|
+
npx afk-code slack setup # Enter your credentials
|
|
70
|
+
npx afk-code slack # Start the bot
|
|
63
71
|
|
|
64
72
|
# 4. In another terminal, start a monitored Claude session
|
|
65
|
-
npx afk-code
|
|
73
|
+
npx afk-code claude
|
|
66
74
|
```
|
|
67
75
|
|
|
76
|
+
A new channel is created for each session. Messages relay bidirectionally.
|
|
77
|
+
|
|
68
78
|
## Commands
|
|
69
79
|
|
|
70
80
|
```
|
|
71
|
-
afk-code slack setup Configure Slack credentials
|
|
72
|
-
afk-code slack Run the Slack bot
|
|
73
|
-
afk-code discord setup Configure Discord credentials
|
|
74
|
-
afk-code discord Run the Discord bot
|
|
75
81
|
afk-code telegram setup Configure Telegram credentials
|
|
76
82
|
afk-code telegram Run the Telegram bot
|
|
77
|
-
afk-code
|
|
83
|
+
afk-code discord setup Configure Discord credentials
|
|
84
|
+
afk-code discord Run the Discord bot
|
|
85
|
+
afk-code slack setup Configure Slack credentials
|
|
86
|
+
afk-code slack Run the Slack bot
|
|
87
|
+
afk-code <command> [args] Start a monitored session
|
|
78
88
|
afk-code help Show help
|
|
79
89
|
```
|
|
80
90
|
|
|
@@ -103,7 +113,7 @@ npx afk-code <command>
|
|
|
103
113
|
git clone https://github.com/clharman/afk-code.git
|
|
104
114
|
cd afk-code && npm install
|
|
105
115
|
npm run dev -- slack
|
|
106
|
-
npm run dev --
|
|
116
|
+
npm run dev -- claude
|
|
107
117
|
```
|
|
108
118
|
|
|
109
119
|
Requires Node.js 18+.
|
|
@@ -111,7 +121,7 @@ Requires Node.js 18+.
|
|
|
111
121
|
## How It Works
|
|
112
122
|
|
|
113
123
|
1. `afk-code slack`, `afk-code discord`, or `afk-code telegram` starts a bot that listens for sessions
|
|
114
|
-
2. `afk-code
|
|
124
|
+
2. `afk-code claude` spawns Claude in a PTY and connects to the bot via Unix socket
|
|
115
125
|
3. The bot watches Claude's JSONL files for messages and relays them to chat
|
|
116
126
|
4. Messages you send in chat are forwarded to the terminal
|
|
117
127
|
|
package/dist/cli/index.js
CHANGED
|
@@ -1597,13 +1597,18 @@ function createTelegramApp(config) {
|
|
|
1597
1597
|
}
|
|
1598
1598
|
processingQueue = false;
|
|
1599
1599
|
}
|
|
1600
|
-
async function sendMessage(text, parseMode = "Markdown") {
|
|
1600
|
+
async function sendMessage(text, parseMode = "Markdown", options) {
|
|
1601
1601
|
messageQueue.push(async () => {
|
|
1602
1602
|
try {
|
|
1603
|
-
await bot.api.sendMessage(config.chatId, text, {
|
|
1603
|
+
await bot.api.sendMessage(config.chatId, text, {
|
|
1604
|
+
parse_mode: parseMode,
|
|
1605
|
+
disable_notification: options?.disable_notification
|
|
1606
|
+
});
|
|
1604
1607
|
} catch (err) {
|
|
1605
1608
|
if (parseMode && err.message?.includes("parse")) {
|
|
1606
|
-
await bot.api.sendMessage(config.chatId, text
|
|
1609
|
+
await bot.api.sendMessage(config.chatId, text, {
|
|
1610
|
+
disable_notification: options?.disable_notification
|
|
1611
|
+
});
|
|
1607
1612
|
} else {
|
|
1608
1613
|
throw err;
|
|
1609
1614
|
}
|
|
@@ -1611,13 +1616,11 @@ function createTelegramApp(config) {
|
|
|
1611
1616
|
});
|
|
1612
1617
|
processQueue();
|
|
1613
1618
|
}
|
|
1614
|
-
async function sendChunkedMessage(text, prefix) {
|
|
1619
|
+
async function sendChunkedMessage(text, prefix, options) {
|
|
1615
1620
|
const chunks = chunkMessage(text, MAX_MESSAGE_LENGTH);
|
|
1616
1621
|
for (let i = 0; i < chunks.length; i++) {
|
|
1617
|
-
const chunk = prefix && i === 0 ? `${prefix}
|
|
1618
|
-
|
|
1619
|
-
${chunks[i]}` : chunks[i];
|
|
1620
|
-
await sendMessage(chunk);
|
|
1622
|
+
const chunk = prefix && i === 0 ? `${prefix} ${chunks[i]}` : chunks[i];
|
|
1623
|
+
await sendMessage(chunk, "Markdown", options);
|
|
1621
1624
|
}
|
|
1622
1625
|
}
|
|
1623
1626
|
const sessionManager = new SessionManager({
|
|
@@ -1627,17 +1630,20 @@ ${chunks[i]}` : chunks[i];
|
|
|
1627
1630
|
sessionName: session.name,
|
|
1628
1631
|
lastActivity: /* @__PURE__ */ new Date()
|
|
1629
1632
|
});
|
|
1633
|
+
const parts = session.name.split(" ");
|
|
1634
|
+
const cmd = parts[0];
|
|
1635
|
+
const args2 = parts.slice(1).map((a) => a.replace(/^-+/, ""));
|
|
1636
|
+
const sessionLabel = args2.length > 0 ? `${cmd} (${args2.join(", ")})` : cmd;
|
|
1630
1637
|
await sendMessage(
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
\`${session.cwd}\``
|
|
1638
|
+
`Session started: ${sessionLabel}
|
|
1639
|
+
Directory: \`${session.cwd}\``
|
|
1634
1640
|
);
|
|
1635
1641
|
},
|
|
1636
1642
|
onSessionEnd: async (sessionId) => {
|
|
1637
1643
|
const tracking = activeSessions.get(sessionId);
|
|
1638
1644
|
const name = tracking?.sessionName || sessionId;
|
|
1639
1645
|
activeSessions.delete(sessionId);
|
|
1640
|
-
await sendMessage(
|
|
1646
|
+
await sendMessage(`Session ended: ${name}`);
|
|
1641
1647
|
},
|
|
1642
1648
|
onSessionUpdate: async (sessionId, name) => {
|
|
1643
1649
|
const tracking = activeSessions.get(sessionId);
|
|
@@ -1662,16 +1668,16 @@ Session started
|
|
|
1662
1668
|
telegramSentMessages.delete(contentKey);
|
|
1663
1669
|
return;
|
|
1664
1670
|
}
|
|
1665
|
-
await sendChunkedMessage(content,
|
|
1671
|
+
await sendChunkedMessage(content, `_User (terminal):_`, { disable_notification: true });
|
|
1666
1672
|
} else {
|
|
1667
|
-
await sendChunkedMessage(content,
|
|
1673
|
+
await sendChunkedMessage(content, `_Claude Code:_`);
|
|
1668
1674
|
}
|
|
1669
1675
|
},
|
|
1670
1676
|
onTodos: async (sessionId, todos) => {
|
|
1671
1677
|
const tracking = activeSessions.get(sessionId);
|
|
1672
1678
|
if (!tracking || todos.length === 0) return;
|
|
1673
1679
|
const todosText = formatTodos(todos);
|
|
1674
|
-
await sendMessage(
|
|
1680
|
+
await sendMessage(`_Claude Code:_ *Tasks:*
|
|
1675
1681
|
${todosText}`);
|
|
1676
1682
|
},
|
|
1677
1683
|
onToolCall: async (_sessionId, _tool) => {
|
|
@@ -1682,7 +1688,7 @@ ${todosText}`);
|
|
|
1682
1688
|
const tracking = activeSessions.get(sessionId);
|
|
1683
1689
|
if (!tracking) return;
|
|
1684
1690
|
const status = inPlanMode ? "Planning mode - Claude is designing a solution" : "Execution mode - Claude is implementing";
|
|
1685
|
-
await sendMessage(
|
|
1691
|
+
await sendMessage(`_Claude Code:_ ${status}`);
|
|
1686
1692
|
}
|
|
1687
1693
|
});
|
|
1688
1694
|
function getCurrentSession() {
|
|
@@ -2504,30 +2510,29 @@ async function main() {
|
|
|
2504
2510
|
AFK Code - Monitor Claude Code sessions from Slack/Discord/Telegram
|
|
2505
2511
|
|
|
2506
2512
|
Commands:
|
|
2507
|
-
slack Run the Slack bot
|
|
2508
|
-
slack setup Configure Slack integration
|
|
2509
|
-
discord Run the Discord bot
|
|
2510
|
-
discord setup Configure Discord integration
|
|
2511
2513
|
telegram Run the Telegram bot
|
|
2512
2514
|
telegram setup Configure Telegram integration
|
|
2513
|
-
|
|
2515
|
+
discord Run the Discord bot
|
|
2516
|
+
discord setup Configure Discord integration
|
|
2517
|
+
slack Run the Slack bot
|
|
2518
|
+
slack setup Configure Slack integration
|
|
2519
|
+
<command> [args] Start a monitored session
|
|
2514
2520
|
help Show this help message
|
|
2515
2521
|
|
|
2516
2522
|
Examples:
|
|
2517
|
-
afk-code slack setup # First-time Slack configuration
|
|
2518
|
-
afk-code slack # Start the Slack bot
|
|
2519
|
-
afk-code discord setup # First-time Discord configuration
|
|
2520
|
-
afk-code discord # Start the Discord bot
|
|
2521
2523
|
afk-code telegram setup # First-time Telegram configuration
|
|
2522
2524
|
afk-code telegram # Start the Telegram bot
|
|
2523
|
-
afk-code
|
|
2525
|
+
afk-code discord setup # First-time Discord configuration
|
|
2526
|
+
afk-code discord # Start the Discord bot
|
|
2527
|
+
afk-code slack setup # First-time Slack configuration
|
|
2528
|
+
afk-code slack # Start the Slack bot
|
|
2529
|
+
afk-code claude # Start a Claude Code session
|
|
2524
2530
|
`);
|
|
2525
2531
|
break;
|
|
2526
2532
|
}
|
|
2527
2533
|
default: {
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
process.exit(1);
|
|
2534
|
+
await run(args);
|
|
2535
|
+
break;
|
|
2531
2536
|
}
|
|
2532
2537
|
}
|
|
2533
2538
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "afk-code",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Monitor and interact with Claude Code sessions from Slack/Discord/Telegram",
|
|
5
5
|
"author": "Colin Harman",
|
|
6
6
|
"repository": {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"cli"
|
|
37
37
|
],
|
|
38
38
|
"license": "MIT",
|
|
39
|
-
|
|
39
|
+
"dependencies": {
|
|
40
40
|
"@slack/bolt": "^4.6.0",
|
|
41
41
|
"discord.js": "^14.25.1",
|
|
42
42
|
"grammy": "^1.35.0",
|