@alexnodeland/claude-telegram 0.1.4 → 0.2.1
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/CHANGELOG.md +23 -0
- package/README.md +46 -17
- package/package.json +4 -2
- package/scripts/daemon.sh +161 -0
- package/src/orchestrator.ts +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.2.1] - 2026-03-22
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **`claude` not found in daemon** — orchestrator now reads `CLAUDE_BIN` env var for the CLI path, falling back to `"claude"` from `$PATH`. Fixes "Executable not found" when launchd/systemd don't inherit the user's full `$PATH`.
|
|
13
|
+
- Daemon install script (`daemon.sh`) auto-detects the `claude` binary path and passes `CLAUDE_BIN` into the launchd plist / systemd unit.
|
|
14
|
+
|
|
15
|
+
## [0.2.0] - 2025-03-22
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **npm distribution** — install via `bun add -g @alexnodeland/claude-telegram`
|
|
20
|
+
- **Daemon script** — `claude-telegram-daemon install` sets up launchd (macOS) or systemd (Linux) automatically
|
|
21
|
+
- **CONTRIBUTING.md** — development setup, code style, testing, and PR guidelines
|
|
22
|
+
- **GitHub Release workflow** — tag-triggered CI, GitHub Release, and npm publish with provenance
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Quick start defaults to npm install instead of git clone
|
|
27
|
+
- Orchestrator and channel mode docs updated for npm install path
|
|
28
|
+
|
|
8
29
|
## [0.1.0] - 2025-03-22
|
|
9
30
|
|
|
10
31
|
### Added
|
|
@@ -23,4 +44,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
23
44
|
- **HTML formatting** — all output uses Telegram HTML parse mode for reliable rendering
|
|
24
45
|
- **Zero Telegram SDK** — all API calls use native `fetch`
|
|
25
46
|
|
|
47
|
+
[0.2.1]: https://github.com/alexnodeland/claude-telegram/releases/tag/v0.2.1
|
|
48
|
+
[0.2.0]: https://github.com/alexnodeland/claude-telegram/releases/tag/v0.2.0
|
|
26
49
|
[0.1.0]: https://github.com/alexnodeland/claude-telegram/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
**Control Claude Code from Telegram — run tasks, review diffs, and ship code from your phone.**
|
|
6
6
|
|
|
7
|
+
[](https://www.npmjs.com/package/@alexnodeland/claude-telegram)
|
|
7
8
|
[](https://github.com/alexnodeland/claude-telegram/releases)
|
|
8
9
|
[](https://github.com/alexnodeland/claude-telegram/actions/workflows/ci.yml)
|
|
9
10
|
[](https://opensource.org/licenses/MIT)
|
|
@@ -54,19 +55,54 @@ Claude Telegram gives you full Claude Code access from any Telegram client — p
|
|
|
54
55
|
|
|
55
56
|
## Quick start
|
|
56
57
|
|
|
57
|
-
|
|
58
|
+
### Prerequisites
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
- [Bun](https://bun.sh) >= 1.1
|
|
61
|
+
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) >= 2.1
|
|
62
|
+
- A Telegram bot token (message [@BotFather](https://t.me/BotFather), send `/newbot`, copy the token)
|
|
63
|
+
|
|
64
|
+
### Install and run
|
|
60
65
|
|
|
61
66
|
```bash
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
67
|
+
# Install the package
|
|
68
|
+
bun add -g @alexnodeland/claude-telegram
|
|
69
|
+
|
|
70
|
+
# Set your bot token
|
|
65
71
|
export TELEGRAM_BOT_TOKEN=your_token_here
|
|
66
|
-
|
|
72
|
+
|
|
73
|
+
# Start the orchestrator
|
|
74
|
+
claude-telegram-orchestrator
|
|
67
75
|
```
|
|
68
76
|
|
|
69
|
-
|
|
77
|
+
Or run directly without installing:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
TELEGRAM_BOT_TOKEN=your_token_here bunx @alexnodeland/claude-telegram/src/orchestrator.ts
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Pair your Telegram account
|
|
84
|
+
|
|
85
|
+
1. Send `/start` to your bot in Telegram
|
|
86
|
+
2. An already-approved user sends `/approve <CODE>` with the 6-character pairing code
|
|
87
|
+
|
|
88
|
+
To pre-approve users on first run, set `TELEGRAM_ALLOWED_USERS` with comma-separated Telegram user IDs:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
TELEGRAM_ALLOWED_USERS=783772449 claude-telegram-orchestrator
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Running as a daemon
|
|
95
|
+
|
|
96
|
+
A built-in script sets up launchd (macOS) or systemd (Linux) automatically:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
claude-telegram-daemon install # install and start
|
|
100
|
+
claude-telegram-daemon status # check if running
|
|
101
|
+
claude-telegram-daemon logs # tail logs
|
|
102
|
+
claude-telegram-daemon uninstall # stop and remove
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Auto-restarts on crash and starts on login. See the [orchestrator docs](docs/orchestrator-mode.md#running-as-a-daemon) for manual setup options.
|
|
70
106
|
|
|
71
107
|
> [!TIP]
|
|
72
108
|
> The **orchestrator mode** above is standalone and manages its own Claude sessions. There's also a [channel mode](docs/channel-mode.md) that attaches Telegram to an existing Claude Code session as an MCP plugin.
|
|
@@ -173,18 +209,11 @@ Anything that isn't a command is sent as a prompt to Claude.
|
|
|
173
209
|
| [Channel Mode](docs/channel-mode.md) | MCP channel plugin setup, pairing, access commands, tools |
|
|
174
210
|
| [Architecture](docs/architecture.md) | System design, module map, security model, data flow |
|
|
175
211
|
| [Changelog](CHANGELOG.md) | Release history |
|
|
212
|
+
| [Contributing](CONTRIBUTING.md) | Development setup, code style, testing, pull requests |
|
|
176
213
|
|
|
177
|
-
##
|
|
178
|
-
|
|
179
|
-
```bash
|
|
180
|
-
just setup # Install deps + configure git hooks
|
|
181
|
-
just dev-orchestrator # Watch mode
|
|
182
|
-
just ci # Typecheck + lint + test (112 tests)
|
|
183
|
-
just fix # Auto-fix lint/format
|
|
184
|
-
just release 1.1.0 # Tag a release
|
|
185
|
-
```
|
|
214
|
+
## Contributing
|
|
186
215
|
|
|
187
|
-
See [
|
|
216
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.
|
|
188
217
|
|
|
189
218
|
## License
|
|
190
219
|
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alexnodeland/claude-telegram",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Claude Code Channel plugin + standalone orchestrator bridging Telegram to Claude Code sessions",
|
|
5
5
|
"module": "src/index.ts",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"bin": {
|
|
9
9
|
"claude-telegram": "./src/index.ts",
|
|
10
|
-
"claude-telegram-orchestrator": "./src/orchestrator.ts"
|
|
10
|
+
"claude-telegram-orchestrator": "./src/orchestrator.ts",
|
|
11
|
+
"claude-telegram-daemon": "./scripts/daemon.sh"
|
|
11
12
|
},
|
|
12
13
|
"scripts": {
|
|
13
14
|
"start": "bun run src/index.ts",
|
|
@@ -36,6 +37,7 @@
|
|
|
36
37
|
},
|
|
37
38
|
"files": [
|
|
38
39
|
"src/",
|
|
40
|
+
"scripts/",
|
|
39
41
|
"LICENSE",
|
|
40
42
|
"README.md",
|
|
41
43
|
"CHANGELOG.md"
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Install/uninstall claude-telegram as a system daemon.
|
|
3
|
+
# Usage: daemon.sh install | uninstall | status | logs
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
# Resolve paths
|
|
7
|
+
BUN="$(which bun 2>/dev/null || echo "$HOME/.bun/bin/bun")"
|
|
8
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
9
|
+
ORCHESTRATOR="$SCRIPT_DIR/src/orchestrator.ts"
|
|
10
|
+
TOKEN="${TELEGRAM_BOT_TOKEN:-}"
|
|
11
|
+
CLAUDE_BIN="${CLAUDE_BIN:-$(which claude 2>/dev/null || echo "claude")}"
|
|
12
|
+
|
|
13
|
+
if [ -z "$TOKEN" ] && [ "$1" != "uninstall" ] && [ "$1" != "status" ] && [ "$1" != "logs" ]; then
|
|
14
|
+
echo "Error: TELEGRAM_BOT_TOKEN is not set"
|
|
15
|
+
echo " export TELEGRAM_BOT_TOKEN=your_token_here"
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
# ── macOS (launchd) ─────────────────────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
PLIST="$HOME/Library/LaunchAgents/com.claude-telegram.plist"
|
|
22
|
+
|
|
23
|
+
install_launchd() {
|
|
24
|
+
cat > "$PLIST" << EOF
|
|
25
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
26
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
27
|
+
<plist version="1.0">
|
|
28
|
+
<dict>
|
|
29
|
+
<key>Label</key>
|
|
30
|
+
<string>com.claude-telegram</string>
|
|
31
|
+
<key>ProgramArguments</key>
|
|
32
|
+
<array>
|
|
33
|
+
<string>$BUN</string>
|
|
34
|
+
<string>run</string>
|
|
35
|
+
<string>$ORCHESTRATOR</string>
|
|
36
|
+
</array>
|
|
37
|
+
<key>EnvironmentVariables</key>
|
|
38
|
+
<dict>
|
|
39
|
+
<key>TELEGRAM_BOT_TOKEN</key>
|
|
40
|
+
<string>$TOKEN</string>
|
|
41
|
+
<key>CLAUDE_BIN</key>
|
|
42
|
+
<string>$CLAUDE_BIN</string>
|
|
43
|
+
<key>PATH</key>
|
|
44
|
+
<string>/usr/local/bin:/usr/bin:/bin:$HOME/.bun/bin</string>
|
|
45
|
+
</dict>
|
|
46
|
+
<key>KeepAlive</key>
|
|
47
|
+
<true/>
|
|
48
|
+
<key>StandardOutPath</key>
|
|
49
|
+
<string>/tmp/claude-telegram.log</string>
|
|
50
|
+
<key>StandardErrorPath</key>
|
|
51
|
+
<string>/tmp/claude-telegram.log</string>
|
|
52
|
+
</dict>
|
|
53
|
+
</plist>
|
|
54
|
+
EOF
|
|
55
|
+
launchctl load "$PLIST"
|
|
56
|
+
echo "Daemon installed and started."
|
|
57
|
+
echo " Logs: tail -f /tmp/claude-telegram.log"
|
|
58
|
+
echo " Stop: $0 uninstall"
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
uninstall_launchd() {
|
|
62
|
+
if [ -f "$PLIST" ]; then
|
|
63
|
+
launchctl unload "$PLIST" 2>/dev/null || true
|
|
64
|
+
rm -f "$PLIST"
|
|
65
|
+
echo "Daemon stopped and removed."
|
|
66
|
+
else
|
|
67
|
+
echo "No daemon installed."
|
|
68
|
+
fi
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
status_launchd() {
|
|
72
|
+
if launchctl list com.claude-telegram &>/dev/null; then
|
|
73
|
+
echo "Running"
|
|
74
|
+
launchctl list com.claude-telegram
|
|
75
|
+
else
|
|
76
|
+
echo "Not running"
|
|
77
|
+
fi
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
logs_launchd() {
|
|
81
|
+
tail -f /tmp/claude-telegram.log
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
# ── Linux (systemd) ─────────────────────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
SERVICE_DIR="$HOME/.config/systemd/user"
|
|
87
|
+
SERVICE="$SERVICE_DIR/claude-telegram.service"
|
|
88
|
+
|
|
89
|
+
install_systemd() {
|
|
90
|
+
mkdir -p "$SERVICE_DIR"
|
|
91
|
+
cat > "$SERVICE" << EOF
|
|
92
|
+
[Unit]
|
|
93
|
+
Description=Claude Telegram Orchestrator
|
|
94
|
+
After=network.target
|
|
95
|
+
|
|
96
|
+
[Service]
|
|
97
|
+
ExecStart=$BUN run $ORCHESTRATOR
|
|
98
|
+
Environment=TELEGRAM_BOT_TOKEN=$TOKEN
|
|
99
|
+
Environment=CLAUDE_BIN=$CLAUDE_BIN
|
|
100
|
+
Restart=on-failure
|
|
101
|
+
RestartSec=5
|
|
102
|
+
|
|
103
|
+
[Install]
|
|
104
|
+
WantedBy=default.target
|
|
105
|
+
EOF
|
|
106
|
+
systemctl --user daemon-reload
|
|
107
|
+
systemctl --user enable --now claude-telegram
|
|
108
|
+
echo "Daemon installed and started."
|
|
109
|
+
echo " Logs: journalctl --user -u claude-telegram -f"
|
|
110
|
+
echo " Stop: $0 uninstall"
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
uninstall_systemd() {
|
|
114
|
+
if [ -f "$SERVICE" ]; then
|
|
115
|
+
systemctl --user disable --now claude-telegram 2>/dev/null || true
|
|
116
|
+
rm -f "$SERVICE"
|
|
117
|
+
systemctl --user daemon-reload
|
|
118
|
+
echo "Daemon stopped and removed."
|
|
119
|
+
else
|
|
120
|
+
echo "No daemon installed."
|
|
121
|
+
fi
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
status_systemd() {
|
|
125
|
+
systemctl --user status claude-telegram 2>/dev/null || echo "Not running"
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
logs_systemd() {
|
|
129
|
+
journalctl --user -u claude-telegram -f
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
# ── Dispatch ─────────────────────────────────────────────────────────────────
|
|
133
|
+
|
|
134
|
+
ACTION="${1:-install}"
|
|
135
|
+
OS="$(uname -s)"
|
|
136
|
+
|
|
137
|
+
case "$OS" in
|
|
138
|
+
Darwin)
|
|
139
|
+
case "$ACTION" in
|
|
140
|
+
install) install_launchd ;;
|
|
141
|
+
uninstall) uninstall_launchd ;;
|
|
142
|
+
status) status_launchd ;;
|
|
143
|
+
logs) logs_launchd ;;
|
|
144
|
+
*) echo "Usage: $0 install|uninstall|status|logs"; exit 1 ;;
|
|
145
|
+
esac
|
|
146
|
+
;;
|
|
147
|
+
Linux)
|
|
148
|
+
case "$ACTION" in
|
|
149
|
+
install) install_systemd ;;
|
|
150
|
+
uninstall) uninstall_systemd ;;
|
|
151
|
+
status) status_systemd ;;
|
|
152
|
+
logs) logs_systemd ;;
|
|
153
|
+
*) echo "Usage: $0 install|uninstall|status|logs"; exit 1 ;;
|
|
154
|
+
esac
|
|
155
|
+
;;
|
|
156
|
+
*)
|
|
157
|
+
echo "Unsupported OS: $OS"
|
|
158
|
+
echo "Use tmux instead: tmux new-session -d -s claude 'claude-telegram-orchestrator'"
|
|
159
|
+
exit 1
|
|
160
|
+
;;
|
|
161
|
+
esac
|
package/src/orchestrator.ts
CHANGED
|
@@ -348,6 +348,7 @@ const MAX_TURNS = Number(process.env.ORCHESTRATOR_MAX_TURNS ?? "50");
|
|
|
348
348
|
let globalModel = process.env.ORCHESTRATOR_MODEL;
|
|
349
349
|
|
|
350
350
|
// Absolute path to the sidecar script
|
|
351
|
+
const CLAUDE_BIN = process.env.CLAUDE_BIN ?? "claude";
|
|
351
352
|
const RELAY_SCRIPT = resolve(import.meta.dir, "permission-relay.ts");
|
|
352
353
|
|
|
353
354
|
process.stderr.write(
|
|
@@ -1258,7 +1259,7 @@ async function runQuery(
|
|
|
1258
1259
|
await writeFile(mcpConfigPath, JSON.stringify(mcpConfig));
|
|
1259
1260
|
|
|
1260
1261
|
const args = [
|
|
1261
|
-
|
|
1262
|
+
CLAUDE_BIN,
|
|
1262
1263
|
"-p",
|
|
1263
1264
|
"--output-format",
|
|
1264
1265
|
"stream-json",
|