better-tg-cli 0.19.0 → 0.21.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 +105 -175
- package/SKILL.md +2 -2
- package/dist/telegram.mjs +1 -1
- package/package.json +5 -4
- package/reference.md +31 -1
package/README.md
CHANGED
|
@@ -1,211 +1,141 @@
|
|
|
1
1
|
# better-tg-cli
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
[](https://github.com/TheVilfer/better-tg-cli/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/better-tg-cli)
|
|
5
|
+
[](https://github.com/TheVilfer/homebrew-tap)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
An unofficial, agent-friendly command-line client for Telegram that runs **on your own account**
|
|
9
|
+
(MTProto via [`teleproto`](https://www.npmjs.com/package/teleproto), TL layer 229). The command is
|
|
10
|
+
`telegram`: about 60 commands for reading, searching, writing, bots, groups and exports, built so
|
|
11
|
+
that AI agents (Claude Code, Codex, …) can drive it cheaply and safely.
|
|
12
|
+
|
|
13
|
+
```console
|
|
14
|
+
$ telegram inbox -n 3
|
|
15
|
+
48 unread in 7 chats (showing 3)
|
|
16
|
+
1234567890 user unread=2 Alice @alice | see you at 7?
|
|
17
|
+
-1001234567 supergroup muted unread=41 Rust Moscow @rust_msk | anyone tried 1.90?
|
|
18
|
+
-1009876543 channel unread=5 Changelog | v2.4 is out
|
|
19
|
+
$ telegram read @alice -n 1 --json
|
|
20
|
+
{"chatTitle":"Alice","messages":[{"id":812,"date":"2026-09-27T10:02:11.000Z","sender":"Alice","senderId":"1234567890","text":"see you at 7?"}]}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Why this fork
|
|
24
|
+
|
|
25
|
+
A fork of [skillhq/telegram](https://github.com/skillhq/telegram), reworked for agents:
|
|
26
|
+
|
|
27
|
+
- **Current Telegram layer.** Bot replies with rich (layer 228+) content show real text instead of
|
|
28
|
+
`(no text)`. You can press bot buttons (`click`) and walk bot menus.
|
|
29
|
+
- **Token-efficient output.** Off a TTY you get one compact line per item with the ID first, and
|
|
30
|
+
JSON on one line with empty fields dropped. `--max-text` trims long posts. `telegram help-all -g
|
|
31
|
+
<word>` prints every flag, generated from the code.
|
|
32
|
+
- **Exact reads.** Real pagination for `--since/--until`, `--unread`, threads and channel
|
|
33
|
+
comments, forum topics, `get` by ID, search filters by type, sender or date, and `me` / `Избранное`
|
|
34
|
+
for Saved Messages.
|
|
35
|
+
- **Safe by default.** The account is read-only until a human runs `write-access on [--for 1h]`
|
|
36
|
+
and confirms it in a terminal prompt or a macOS dialog, so an agent cannot switch it on itself.
|
|
37
|
+
Every write is logged to `~/.config/tg/audit.jsonl`. Secrets live in the macOS Keychain or in
|
|
38
|
+
1Password.
|
|
39
|
+
- **Small and self-contained.** The npm package is one 0.3 MB file with zero runtime
|
|
40
|
+
dependencies. Homebrew installs a standalone binary with no Node.
|
|
41
|
+
|
|
42
|
+
## Install
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
brew install thevilfer/tap/better-tg-cli # standalone binary, macOS and Linux
|
|
12
46
|
npm install -g better-tg-cli # Node >= 20
|
|
13
47
|
```
|
|
14
48
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
git clone https://github.com/TheVilfer/better-tg-cli.git ~/.agents/skills/telegram
|
|
20
|
-
ln -s ~/.agents/skills/telegram ~/.claude/skills/telegram
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
To build from source you need Node >= 20 and [Bun](https://bun.sh) (the bundler):
|
|
24
|
-
`npm install && npm run build && npm install -g .` (or `./install.sh`).
|
|
25
|
-
|
|
26
|
-
### Updating
|
|
27
|
-
|
|
28
|
-
`telegram update` updates the way it was installed: `brew upgrade`, `npm install -g better-tg-cli@latest`,
|
|
29
|
-
or `git pull --ff-only` + build for a checkout. `telegram update --check` only reports.
|
|
30
|
-
On a terminal the CLI checks npm once a day in the background and prints a one-line notice when a
|
|
31
|
-
new version is out; piped output (agents) never gets it. `TG_NO_UPDATE_CHECK=1` turns it off.
|
|
32
|
-
|
|
33
|
-
Hacking on the CLI: see [DEVELOPMENT.md](DEVELOPMENT.md) (run from source, isolated dev profile, debugger).
|
|
34
|
-
|
|
35
|
-
Do **not** install `@skillhq/telegram`. That is the old upstream build on GramJS (layer 198), and
|
|
36
|
-
bot replies show up as `(no text)`.
|
|
37
|
-
|
|
38
|
-
**Linux note:** secrets go to the macOS Keychain or to 1Password (`telegram auth --op-vault`).
|
|
39
|
-
Without either, the session is kept in `~/.config/tg/config.json5` (mode 0600), and write
|
|
40
|
-
commands stay disabled.
|
|
41
|
-
|
|
42
|
-
## Authentication
|
|
49
|
+
`telegram update` upgrades an existing install, whichever of these you used. On a terminal the CLI
|
|
50
|
+
checks for new versions once a day. Agents and pipes never see that notice, and
|
|
51
|
+
`TG_NO_UPDATE_CHECK=1` turns it off.
|
|
43
52
|
|
|
44
|
-
**
|
|
45
|
-
1. Go to https://my.telegram.org/apps and log in with your phone number
|
|
46
|
-
2. Create an application and copy its `api_id` and `api_hash`
|
|
47
|
-
3. Run `telegram auth` and enter them, then your phone, the login code and your 2FA password
|
|
53
|
+
Do **not** install `@skillhq/telegram`. It is the old upstream build on GramJS (layer 198).
|
|
48
54
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
telegram auth --invite # paste the token when asked (or: TG_INVITE=... / --invite -)
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
The invite service (`broker/`) hands out the app's keys once for your login. The `api_hash` is
|
|
56
|
-
not stored on your machine afterwards, only the `api_id` and your session. Invites are personal,
|
|
57
|
-
limited to a few logins, and can be revoked.
|
|
58
|
-
|
|
59
|
-
Your session is stored in the macOS Keychain (service `tg-cli`), or in 1Password with
|
|
60
|
-
`--op-vault`. `telegram logout` removes it.
|
|
61
|
-
|
|
62
|
-
## Commands
|
|
63
|
-
|
|
64
|
-
### Auth & Status
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
telegram whoami # Show logged-in account
|
|
68
|
-
telegram check # Verify session/credentials
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### Reading
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
telegram chats # List all chats
|
|
75
|
-
telegram chats --type group # Filter by type (user, group, supergroup, channel)
|
|
76
|
-
telegram read "MetaDAO Community" -n 50 # Read last 50 messages
|
|
77
|
-
telegram read "MetaDAO" --since "1h" # Messages from last hour
|
|
78
|
-
telegram read @username -n 20 # Read DM with user
|
|
79
|
-
telegram search "futarchy" --chat "MetaDAO" # Search within chat
|
|
80
|
-
telegram search "futarchy" --all # Search all chats
|
|
81
|
-
telegram inbox # Unread messages summary
|
|
82
|
-
```
|
|
55
|
+
### As an agent skill
|
|
83
56
|
|
|
84
|
-
|
|
57
|
+
The repo itself is the skill (`SKILL.md` + `reference.md`):
|
|
85
58
|
|
|
86
59
|
```bash
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
telegram reply "ChatName" 12345 "Response" # Reply to message ID
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### Bot Buttons
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
telegram buttons @SomeBot 12345 # List buttons on a message
|
|
96
|
-
telegram click @SomeBot 12345 2 # Press button #2 (by index)
|
|
97
|
-
telegram click @SomeBot 12345 "Settings" # Press by label
|
|
98
|
-
telegram click @SomeBot 12345 1 --json # Machine-readable outcome
|
|
60
|
+
git clone https://github.com/TheVilfer/better-tg-cli.git ~/.agents/skills/telegram
|
|
61
|
+
ln -s ~/.agents/skills/telegram ~/.claude/skills/telegram
|
|
99
62
|
```
|
|
100
63
|
|
|
101
|
-
|
|
102
|
-
press, `click` re-reads the message so you see the bot's edited reply and its
|
|
103
|
-
new buttons — enough to navigate a bot's menus step by step. `click` needs
|
|
104
|
-
write access enabled.
|
|
105
|
-
|
|
106
|
-
### Reactions, Forwarding & Pinning
|
|
64
|
+
## Log in
|
|
107
65
|
|
|
108
|
-
|
|
109
|
-
telegram
|
|
110
|
-
telegram
|
|
111
|
-
telegram forward "FromChat" 12345 "ToChat" # Forward message(s); comma-separate IDs
|
|
112
|
-
telegram pin "ChatName" 12345 # Pin (--notify to alert members)
|
|
113
|
-
telegram unpin "ChatName" 12345 # Unpin one; omit ID to unpin all
|
|
114
|
-
```
|
|
66
|
+
**With your own API keys** (the default):
|
|
67
|
+
1. Open https://my.telegram.org/apps, create an application, and copy its `api_id` and `api_hash`.
|
|
68
|
+
2. Run `telegram auth` and enter them, then your phone number, the login code and your 2FA password.
|
|
115
69
|
|
|
116
|
-
|
|
70
|
+
**With an invite.** If the maintainer gave you an invite token, you don't need your own keys.
|
|
71
|
+
Run `telegram auth --invite` and paste the token, or pass it as `TG_INVITE=…` or `--invite -`. The
|
|
72
|
+
invite service (`broker/`) hands out the app's keys once, for this login only. The `api_hash` is not
|
|
73
|
+
kept on your machine. Invites are personal, allow a limited number of logins, and can be revoked.
|
|
117
74
|
|
|
118
|
-
|
|
119
|
-
telegram
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
telegram send @user "later" --schedule 2h # Schedule a message
|
|
125
|
-
telegram poll "Chat" "Q?" A B C # Send a poll
|
|
126
|
-
telegram vote "Chat" 12345 2 # Vote for option #2
|
|
127
|
-
```
|
|
75
|
+
The session is stored in the macOS Keychain (service `tg-cli`), or in 1Password with
|
|
76
|
+
`--op-vault <vault>`. `telegram logout` removes it. On Linux it goes to the Secret Service (GNOME
|
|
77
|
+
Keyring, KWallet, KeePassXC) through `secret-tool`, which needs the `libsecret-tools` package. A
|
|
78
|
+
session already saved in the config file moves there automatically. Without any secret store, the
|
|
79
|
+
session is kept in `~/.config/tg/config.json5` (mode 0600) and write commands stay disabled.
|
|
80
|
+
On Linux, `write-access on` is confirmed at a terminal prompt.
|
|
128
81
|
|
|
129
|
-
|
|
82
|
+
## Usage
|
|
130
83
|
|
|
131
84
|
```bash
|
|
132
|
-
telegram
|
|
133
|
-
telegram
|
|
134
|
-
telegram
|
|
135
|
-
telegram
|
|
136
|
-
telegram
|
|
137
|
-
telegram
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
All of the above except reads (`reactions`, `pinned`, `watch`, `avatar`, `inline`, `stories`) are write operations and need write access enabled.
|
|
141
|
-
|
|
142
|
-
### Contacts & Groups
|
|
85
|
+
telegram chats --type channel # one line per chat, ID first
|
|
86
|
+
telegram read "Chat" --since 1h # exact range, newest first (--asc to flip)
|
|
87
|
+
telegram read @channel --thread 123 # comments under a post
|
|
88
|
+
telegram search "invoice" --chat "Work" --type document
|
|
89
|
+
telegram get "Chat" 812 813 # exact messages by ID
|
|
90
|
+
telegram download "Chat" 812 # save the attached file
|
|
91
|
+
telegram sync --chat "Chat" --output ./export --resume # incremental markdown export
|
|
143
92
|
|
|
144
|
-
|
|
145
|
-
telegram
|
|
146
|
-
telegram
|
|
147
|
-
telegram
|
|
148
|
-
telegram groups # List all groups
|
|
149
|
-
telegram groups --admin # Groups where you're admin
|
|
150
|
-
telegram kick "GroupName" @username # Remove a user from a group
|
|
151
|
-
telegram promote "GroupName" @username # Promote a member to admin
|
|
152
|
-
telegram transfer-owner "GroupName" @username # Transfer ownership (prompts for 2FA password)
|
|
93
|
+
telegram write-access on --for 1h # a human confirms this
|
|
94
|
+
printf '%s' "$text" | telegram send @alice - # text from stdin, no quoting problems
|
|
95
|
+
telegram reply "Chat" 812 "on it" --silent
|
|
96
|
+
telegram click @SomeBot 4410 "Settings" # press an inline button
|
|
153
97
|
```
|
|
154
98
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
### Muting
|
|
99
|
+
Read commands take `--json`, and some also take `--markdown`. See all commands with
|
|
100
|
+
`telegram help-all`. [reference.md](reference.md) covers the behaviour that the flag list can't
|
|
101
|
+
explain: output shapes, threads, bot buttons, admin commands and troubleshooting.
|
|
160
102
|
|
|
161
|
-
|
|
162
|
-
telegram mute "ChatName" # Mute forever
|
|
163
|
-
telegram mute "ChatName" -d 1h # Mute for 1 hour
|
|
164
|
-
telegram mute @username -d 8h # Mute DM for 8 hours
|
|
165
|
-
telegram unmute "ChatName" # Unmute
|
|
166
|
-
```
|
|
103
|
+
## MCP server
|
|
167
104
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
telegram folder-add "Work" "ProjectChat" # Add chat to folder
|
|
174
|
-
telegram folder-remove "Work" "ProjectChat" # Remove chat from folder
|
|
175
|
-
```
|
|
105
|
+
For clients without a shell (Claude Desktop, Cursor, other MCP hosts), `telegram mcp` serves three
|
|
106
|
+
tools over stdio:
|
|
107
|
+
- `telegram_help`: a searchable flag reference;
|
|
108
|
+
- `telegram_read`: read-only, so clients may auto-approve it;
|
|
109
|
+
- `telegram_write`: marked destructive, and still needs `write-access on` from you.
|
|
176
110
|
|
|
177
|
-
|
|
111
|
+
Log in with `telegram auth` in a terminal first.
|
|
178
112
|
|
|
179
113
|
```bash
|
|
180
|
-
|
|
181
|
-
telegram sync --chat "MetaDAO" --days 30 # Sync specific chat
|
|
114
|
+
claude mcp add telegram -- telegram mcp # Claude Code
|
|
182
115
|
```
|
|
183
116
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
All read commands support multiple output formats:
|
|
187
|
-
|
|
188
|
-
```bash
|
|
189
|
-
telegram chats --json # JSON (for scripts/AI)
|
|
190
|
-
telegram read "Chat" --markdown # Markdown format
|
|
191
|
-
telegram inbox --plain # Plain text (no colors)
|
|
117
|
+
```json
|
|
118
|
+
{ "mcpServers": { "telegram": { "command": "/opt/homebrew/bin/telegram", "args": ["mcp"] } } }
|
|
192
119
|
```
|
|
193
120
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
- `config.json` - API credentials and session
|
|
198
|
-
- Session data is encrypted and stored securely
|
|
121
|
+
Use the second form for Claude Desktop (`claude_desktop_config.json`) or Cursor (`.cursor/mcp.json`).
|
|
122
|
+
GUI apps may not see your shell PATH, so give the full path from `which telegram`. To keep the MCP
|
|
123
|
+
client off your main session, add `"env": {"TG_PROFILE": "work"}`.
|
|
199
124
|
|
|
200
125
|
## Development
|
|
201
126
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
127
|
+
[DEVELOPMENT.md](DEVELOPMENT.md) covers:
|
|
128
|
+
- running from source (`scripts/tg-dev`);
|
|
129
|
+
- isolated dev profiles (`TG_PROFILE`) that never touch your real session;
|
|
130
|
+
- Telegram test servers;
|
|
131
|
+
- editor debugging and tests.
|
|
132
|
+
|
|
133
|
+
Releases are cut by `scripts/release.sh patch|minor|major`. A tag builds the binaries and
|
|
134
|
+
publishes to GitHub Releases, npm (trusted publishing with provenance) and the Homebrew tap. See
|
|
135
|
+
[CONTRIBUTING.md](CONTRIBUTING.md).
|
|
207
136
|
|
|
208
137
|
## License
|
|
209
138
|
|
|
210
|
-
MIT
|
|
211
|
-
|
|
139
|
+
MIT, see [LICENSE](LICENSE). Based on [skillhq/telegram](https://github.com/skillhq/telegram) by
|
|
140
|
+
Derek Rein. Not affiliated with or endorsed by Telegram; "Telegram" is a trademark of its owner.
|
|
141
|
+
Use it in line with the [Telegram API Terms of Service](https://core.telegram.org/api/terms).
|
package/SKILL.md
CHANGED
|
@@ -7,11 +7,11 @@ description: Full-featured Telegram CLI on the user's own account — read, sear
|
|
|
7
7
|
|
|
8
8
|
`telegram <command>` runs on the user's own account (MTProto, not a bot).
|
|
9
9
|
|
|
10
|
-
**Before using an unfamiliar flag, run `telegram help-all -g <word>`.** It lists every command and flag, generated from the code, so it is always current. For behaviour details (threads, bot buttons, sync, JSON shapes, errors), read `reference.md` next to this file.
|
|
10
|
+
**Before using an unfamiliar flag, run `telegram help-all -g <word>`.** It lists every command and flag, generated from the code, so it is always current. For behaviour details (threads, bot buttons, sync, JSON shapes, errors), read `reference.md` next to this file. If the `telegram_read` and `telegram_write` MCP tools are available (`telegram mcp`), they take the same argv as the CLI.
|
|
11
11
|
|
|
12
12
|
## Rules
|
|
13
13
|
|
|
14
|
-
- **Chat identifiers:** `me` means Saved Messages. A numeric ID is matched exactly (use the ID shown first in `chats`/`inbox`/`search` output). `@username` resolves exactly.
|
|
14
|
+
- **Chat identifiers:** `me` means Saved Messages. A numeric ID is matched exactly (use the ID shown first in `chats`/`inbox`/`search` output). `@username` resolves exactly. For reads, any other text matches chat titles by **substring**. Writes accept only an exact, unique title and otherwise refuse, listing candidate IDs. Retry with the ID.
|
|
15
15
|
- **Writes are off by default.** A write fails with "Write access is disabled". Only the user can turn writes on. `telegram write-access on --for 1h` shows them a confirmation dialog, which you cannot click yourself. Ask first, run it, and wait for their click. Get explicit approval for every message to other people and show the final text first.
|
|
16
16
|
- **Save tokens:**
|
|
17
17
|
- Start with `inbox --unmuted`, `chats -q <name>` or `search`, not a full `read`.
|