better-tg-cli 0.17.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/LICENSE +22 -0
- package/README.md +202 -0
- package/SKILL.md +56 -0
- package/dist/telegram.mjs +11 -0
- package/package.json +59 -0
- package/reference.md +126 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Derek Rein (original skillhq/telegram)
|
|
4
|
+
Copyright (c) 2026 Sergei Polin (better-tg-cli modifications)
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# better-tg-cli
|
|
2
|
+
|
|
3
|
+
An unofficial, agent-friendly command-line client for Telegram on your own account (MTProto via `teleproto`, TL layer 229).
|
|
4
|
+
The binary is `telegram`. Fork of [skillhq/telegram](https://github.com/skillhq/telegram) with bot
|
|
5
|
+
buttons, rich (layer 228+) bot replies, threads and forum topics, compact output for agents, and
|
|
6
|
+
about 60 commands. Run `telegram help-all` for the full command and flag list.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
brew install thevilfer/tap/better-tg-cli # standalone binary, macOS and Linux, no Node needed
|
|
12
|
+
npm install -g better-tg-cli # Node >= 20
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Both install the `telegram` command. To use it as an agent skill (Claude Code, Codex), clone the
|
|
16
|
+
repo into the skills folder. That folder is the skill (`SKILL.md` + `reference.md`):
|
|
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
|
+
Do **not** install `@skillhq/telegram`. That is the old upstream build on GramJS (layer 198), and
|
|
27
|
+
bot replies show up as `(no text)`.
|
|
28
|
+
|
|
29
|
+
**Linux note:** secrets go to the macOS Keychain or to 1Password (`telegram auth --op-vault`).
|
|
30
|
+
Without either, the session is kept in `~/.config/tg/config.json5` (mode 0600), and write
|
|
31
|
+
commands stay disabled.
|
|
32
|
+
|
|
33
|
+
## Authentication
|
|
34
|
+
|
|
35
|
+
**Your own API keys (default, for everyone):**
|
|
36
|
+
1. Go to https://my.telegram.org/apps and log in with your phone number
|
|
37
|
+
2. Create an application and copy its `api_id` and `api_hash`
|
|
38
|
+
3. Run `telegram auth` and enter them, then your phone, the login code and your 2FA password
|
|
39
|
+
|
|
40
|
+
**With an invite.** If the maintainer gave you an invite token, you don't need your own keys:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
telegram auth --invite # paste the token when asked (or: TG_INVITE=... / --invite -)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The invite service (`broker/`) hands out the app's keys once for your login. The `api_hash` is
|
|
47
|
+
not stored on your machine afterwards, only the `api_id` and your session. Invites are personal,
|
|
48
|
+
limited to a few logins, and can be revoked.
|
|
49
|
+
|
|
50
|
+
Your session is stored in the macOS Keychain (service `tg-cli`), or in 1Password with
|
|
51
|
+
`--op-vault`. `telegram logout` removes it.
|
|
52
|
+
|
|
53
|
+
## Commands
|
|
54
|
+
|
|
55
|
+
### Auth & Status
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
telegram whoami # Show logged-in account
|
|
59
|
+
telegram check # Verify session/credentials
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Reading
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
telegram chats # List all chats
|
|
66
|
+
telegram chats --type group # Filter by type (user, group, supergroup, channel)
|
|
67
|
+
telegram read "MetaDAO Community" -n 50 # Read last 50 messages
|
|
68
|
+
telegram read "MetaDAO" --since "1h" # Messages from last hour
|
|
69
|
+
telegram read @username -n 20 # Read DM with user
|
|
70
|
+
telegram search "futarchy" --chat "MetaDAO" # Search within chat
|
|
71
|
+
telegram search "futarchy" --all # Search all chats
|
|
72
|
+
telegram inbox # Unread messages summary
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Writing
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
telegram send @username "Hello" # Send DM
|
|
79
|
+
telegram send "GroupName" "Hello everyone" # Send to group
|
|
80
|
+
telegram reply "ChatName" 12345 "Response" # Reply to message ID
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Bot Buttons
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
telegram buttons @SomeBot 12345 # List buttons on a message
|
|
87
|
+
telegram click @SomeBot 12345 2 # Press button #2 (by index)
|
|
88
|
+
telegram click @SomeBot 12345 "Settings" # Press by label
|
|
89
|
+
telegram click @SomeBot 12345 1 --json # Machine-readable outcome
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Buttons show up inline in `read`/`inbox`/`search` output. After a callback
|
|
93
|
+
press, `click` re-reads the message so you see the bot's edited reply and its
|
|
94
|
+
new buttons — enough to navigate a bot's menus step by step. `click` needs
|
|
95
|
+
write access enabled.
|
|
96
|
+
|
|
97
|
+
### Reactions, Forwarding & Pinning
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
telegram react "ChatName" 12345 👍 # React with an emoji (--big, --remove)
|
|
101
|
+
telegram reactions "ChatName" 12345 # List who reacted
|
|
102
|
+
telegram forward "FromChat" 12345 "ToChat" # Forward message(s); comma-separate IDs
|
|
103
|
+
telegram pin "ChatName" 12345 # Pin (--notify to alert members)
|
|
104
|
+
telegram unpin "ChatName" 12345 # Unpin one; omit ID to unpin all
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Editing, Deleting, Polls & Formatting
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
telegram edit "Chat" 12345 "new text" # Edit your own message
|
|
111
|
+
telegram delete "Chat" 12,13 --just-me # Delete (revoke by default)
|
|
112
|
+
telegram mark-read "Chat" # Clear unread badge
|
|
113
|
+
telegram pinned "Chat" # List pinned messages
|
|
114
|
+
telegram send @user "<b>hi</b>" --html # HTML/Markdown formatting (--markdown)
|
|
115
|
+
telegram send @user "later" --schedule 2h # Schedule a message
|
|
116
|
+
telegram poll "Chat" "Q?" A B C # Send a poll
|
|
117
|
+
telegram vote "Chat" 12345 2 # Vote for option #2
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Real-time, Chats & Profile
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
telegram watch "Chat" -t 30 # Stream new messages (timeout/limit required)
|
|
124
|
+
telegram join @channel # Join (also invite links); leave/create-group/create-channel
|
|
125
|
+
telegram archive "Chat" # Archive / unarchive; invite-link "Chat"
|
|
126
|
+
telegram block @user # block/unblock; add-contact/del-contact
|
|
127
|
+
telegram set-name "First" "Last" # set-bio / set-username / set-avatar
|
|
128
|
+
telegram avatar @user # Download avatar; inline @gif "cat"; stories @user
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
All of the above except reads (`reactions`, `pinned`, `watch`, `avatar`, `inline`, `stories`) are write operations and need write access enabled.
|
|
132
|
+
|
|
133
|
+
### Contacts & Groups
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
telegram contact @username # Get contact info
|
|
137
|
+
telegram members "GroupName" # List group members
|
|
138
|
+
telegram admins "GroupName" # List admins only
|
|
139
|
+
telegram groups # List all groups
|
|
140
|
+
telegram groups --admin # Groups where you're admin
|
|
141
|
+
telegram kick "GroupName" @username # Remove a user from a group
|
|
142
|
+
telegram promote "GroupName" @username # Promote a member to admin
|
|
143
|
+
telegram transfer-owner "GroupName" @username # Transfer ownership (prompts for 2FA password)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
> `transfer-owner` is irreversible and requires two-step verification on your account.
|
|
147
|
+
> It works on supergroups/channels only, prompts for your 2FA password securely, and asks
|
|
148
|
+
> you to retype the group name to confirm (`-y` skips the confirmation).
|
|
149
|
+
|
|
150
|
+
### Muting
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
telegram mute "ChatName" # Mute forever
|
|
154
|
+
telegram mute "ChatName" -d 1h # Mute for 1 hour
|
|
155
|
+
telegram mute @username -d 8h # Mute DM for 8 hours
|
|
156
|
+
telegram unmute "ChatName" # Unmute
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Folders
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
telegram folders # List all folders
|
|
163
|
+
telegram folder "Work" # Show chats in folder
|
|
164
|
+
telegram folder-add "Work" "ProjectChat" # Add chat to folder
|
|
165
|
+
telegram folder-remove "Work" "ProjectChat" # Remove chat from folder
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Utilities
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
telegram sync --days 7 # Sync last 7 days to markdown
|
|
172
|
+
telegram sync --chat "MetaDAO" --days 30 # Sync specific chat
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Output Formats
|
|
176
|
+
|
|
177
|
+
All read commands support multiple output formats:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
telegram chats --json # JSON (for scripts/AI)
|
|
181
|
+
telegram read "Chat" --markdown # Markdown format
|
|
182
|
+
telegram inbox --plain # Plain text (no colors)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Configuration
|
|
186
|
+
|
|
187
|
+
Configuration is stored in `~/.config/tg/`:
|
|
188
|
+
- `config.json` - API credentials and session
|
|
189
|
+
- Session data is encrypted and stored securely
|
|
190
|
+
|
|
191
|
+
## Development
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
npm install
|
|
195
|
+
npm run build
|
|
196
|
+
npm run dev # Watch mode
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## License
|
|
200
|
+
|
|
201
|
+
MIT — see [LICENSE](LICENSE). Based on [skillhq/telegram](https://github.com/skillhq/telegram)
|
|
202
|
+
by Derek Rein. Not affiliated with or endorsed by Telegram; "Telegram" is a trademark of its owner.
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: telegram
|
|
3
|
+
description: Full-featured Telegram CLI on the user's own account — read, search, send, edit and delete messages, read comments/threads and forum topics, manage groups and channels, press bot buttons, react, forward, pin, poll/vote, watch live messages, manage contacts and your own profile, and sync history. Use when the user asks about Telegram messages, wants to check inbox or unread, search chats, send/edit/delete messages, format messages, schedule a message, mute/unmute chats, kick/block users, press bot buttons or navigate bot menus, react with emoji, forward or pin messages, create polls or vote, join/leave/create/archive chats, get invite or message links, watch for new messages in real time, query inline bots, read stories, download media or avatars, manage contacts, or update their own name/bio/username/avatar. Also «телеграм», «тг», «телега», «проверь телеграм», «что в тг», «напиши в телеграм», «прочитай чат», «найди в телеге».
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Telegram CLI
|
|
7
|
+
|
|
8
|
+
`telegram <command>` runs on the user's own account (MTProto, not a bot).
|
|
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.
|
|
11
|
+
|
|
12
|
+
## Rules
|
|
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. Any other text matches chat titles by **substring**. For writes, use an ID or @username.
|
|
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
|
+
- **Save tokens:**
|
|
17
|
+
- Start with `inbox --unmuted`, `chats -q <name>` or `search`, not a full `read`.
|
|
18
|
+
- Add `--max-text 200` when skimming.
|
|
19
|
+
- Use `get <chat> <id>` to fetch exactly what you need.
|
|
20
|
+
- Plain output off a TTY is already compact, one line per item with the ID first. Use `--json` only when you parse with jq.
|
|
21
|
+
- **Long or multi-line text:** pass `-` and pipe it through stdin (`printf '%s' "$text" | telegram send <chat> -`). This avoids quoting bugs.
|
|
22
|
+
|
|
23
|
+
## Core commands
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
telegram inbox --unmuted -n 20 # unread chats, most unread first (IDs first)
|
|
27
|
+
telegram chats -q "name" # find a chat's ID; --unread, --type channel, --archived
|
|
28
|
+
telegram read <chat> -n 20 # newest first; --asc, --since 1d, --until 2026-09-01
|
|
29
|
+
telegram read <chat> --unread # only what the user hasn't read yet
|
|
30
|
+
telegram read <chat> --from @user # one sender; --before/--after <msgId> for paging
|
|
31
|
+
telegram read <chat> --thread <postId> # comments under a post; posts with comments show 💬N in read output
|
|
32
|
+
telegram topics <forum> ; telegram read <forum> --topic <id>
|
|
33
|
+
telegram get <chat> <id> [id...] # exact messages
|
|
34
|
+
telegram search "query" -n 20 # global; --chat <c> [--from @u], --type photo|url|document|voice|mentions, --since 7d
|
|
35
|
+
telegram info <chat> # members, about, linked comments chat, forum?
|
|
36
|
+
telegram members <group> -q name ; telegram contacts -q name
|
|
37
|
+
telegram send <chat> "text" # --reply-to <id>, --topic <id>, --html, --silent, --schedule 2h
|
|
38
|
+
telegram reply <chat> <msgId> "text"
|
|
39
|
+
telegram send-file <chat> ./file.pdf -c "caption"
|
|
40
|
+
telegram edit <chat> <msgId> "new text" ; telegram delete <chat> <id,id>
|
|
41
|
+
telegram click <bot> <msgId> <index|label> # press a bot button; `read` shows [index] label (type)
|
|
42
|
+
telegram react <chat> <msgId> 👍 ; telegram forward <from> <ids> <to> ; telegram pin <chat> <id>
|
|
43
|
+
telegram download <chat> <msgId> -o ./dir
|
|
44
|
+
telegram link <chat> <msgId> # t.me link (channels/supergroups)
|
|
45
|
+
telegram watch [chat] -t 60 -n 10 --json # live stream; always bound it with -t/-n
|
|
46
|
+
telegram sync --chat <c> --output ./dir --resume # markdown export, incremental
|
|
47
|
+
telegram mark-read <chat> ; telegram mute <chat> -d 8h
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## JSON shapes (with `--json`)
|
|
51
|
+
|
|
52
|
+
`chats`, `contacts` and `members` return an array. `read` and `get` return `{chatTitle, messages[]}`. `search` returns an array of `{messages[]}`, and global hits carry `chatId` and `chatTitle`. `inbox` returns `{totalUnread, chatsWithUnread, chats[]}`; it skips archived chats unless you pass `--include-archived`, and the totals cover all chats even when `-n` cuts the list. Chat objects have `id`, `title`, `type`, `username`, `unreadCount`, `muted`, `archived` and `lastMessage`. Messages have `id`, `date`, `sender`, `senderId`, `text`, `replyToMsgId`, `isOutgoing`, `media`, `buttons` and `replies` (the comment count). Empty fields are omitted.
|
|
53
|
+
|
|
54
|
+
## If `telegram` is missing
|
|
55
|
+
|
|
56
|
+
Reinstall with `brew install thevilfer/tap/better-tg-cli` or `npm install -g better-tg-cli`, or from this folder with `npm install && npm run build && npm install -g .` (needs Bun). **Never** install `@skillhq/telegram` from npm or update this skill with the skills CLI: that is an old GramJS build, and bot replies come back as `(no text)`.
|