tlgr-cli 2.0.1__py3-none-any.whl
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.
- tlgr/__init__.py +3 -0
- tlgr/__main__.py +6 -0
- tlgr/actions/__init__.py +45 -0
- tlgr/actions/forward.py +74 -0
- tlgr/actions/reply.py +32 -0
- tlgr/cli/__init__.py +259 -0
- tlgr/cli/confirm.py +55 -0
- tlgr/cli/errors.py +84 -0
- tlgr/cli/gen.py +690 -0
- tlgr/cli/globals.py +273 -0
- tlgr/cli/introspect.py +170 -0
- tlgr/cli/params.py +189 -0
- tlgr/cli/render.py +418 -0
- tlgr/core/__init__.py +0 -0
- tlgr/core/accounts.py +384 -0
- tlgr/core/config.py +358 -0
- tlgr/core/custom_tl.py +170 -0
- tlgr/core/errors.py +687 -0
- tlgr/core/eventtypes.py +1170 -0
- tlgr/core/identity.py +127 -0
- tlgr/core/launchd.py +122 -0
- tlgr/core/logging.py +194 -0
- tlgr/core/media.py +134 -0
- tlgr/core/output.py +251 -0
- tlgr/core/pagination.py +227 -0
- tlgr/core/paths.py +360 -0
- tlgr/core/peers.py +427 -0
- tlgr/core/process.py +138 -0
- tlgr/core/signing.py +38 -0
- tlgr/core/systemd.py +96 -0
- tlgr/core/telethon_compat.py +295 -0
- tlgr/core/text.py +211 -0
- tlgr/core/timefmt.py +199 -0
- tlgr/core/tl.py +98 -0
- tlgr/daemon/__init__.py +0 -0
- tlgr/daemon/app.py +869 -0
- tlgr/daemon/dispatch.py +446 -0
- tlgr/daemon/events.py +723 -0
- tlgr/daemon/files.py +431 -0
- tlgr/daemon/idle.py +119 -0
- tlgr/daemon/jobs.py +68 -0
- tlgr/daemon/main.py +161 -0
- tlgr/daemon/peercred.py +75 -0
- tlgr/daemon/policy.py +113 -0
- tlgr/daemon/preauth.py +366 -0
- tlgr/daemon/ratelimit.py +391 -0
- tlgr/daemon/server.py +24 -0
- tlgr/daemon/session.py +648 -0
- tlgr/daemon/sessions.py +274 -0
- tlgr/daemon/singleton.py +114 -0
- tlgr/daemon/stream.py +193 -0
- tlgr/daemon/transfers.py +219 -0
- tlgr/daemon/webhook.py +390 -0
- tlgr/data/catalog_index.json +1 -0
- tlgr/data/parity_waivers.toml +90 -0
- tlgr/filters/__init__.py +42 -0
- tlgr/filters/compose.py +121 -0
- tlgr/filters/content.py +85 -0
- tlgr/filters/context.py +114 -0
- tlgr/filters/message.py +161 -0
- tlgr/filters/temporal.py +87 -0
- tlgr/filters/user.py +36 -0
- tlgr/gateway/__init__.py +1 -0
- tlgr/gateway/config.py +161 -0
- tlgr/gateway/engine.py +215 -0
- tlgr/gateway/event.py +22 -0
- tlgr/jobs/__init__.py +0 -0
- tlgr/jobs/base.py +81 -0
- tlgr/jobs/client.py +37 -0
- tlgr/models/__init__.py +1220 -0
- tlgr/models/admin.py +744 -0
- tlgr/models/auth.py +510 -0
- tlgr/models/base.py +81 -0
- tlgr/models/bot.py +576 -0
- tlgr/models/business.py +265 -0
- tlgr/models/call.py +586 -0
- tlgr/models/config.py +101 -0
- tlgr/models/contact.py +481 -0
- tlgr/models/daemon.py +336 -0
- tlgr/models/dialog.py +626 -0
- tlgr/models/envelope.py +68 -0
- tlgr/models/error.py +30 -0
- tlgr/models/event.py +79 -0
- tlgr/models/export.py +66 -0
- tlgr/models/gift.py +275 -0
- tlgr/models/inline.py +84 -0
- tlgr/models/location.py +115 -0
- tlgr/models/media.py +507 -0
- tlgr/models/message.py +584 -0
- tlgr/models/net.py +232 -0
- tlgr/models/notify.py +105 -0
- tlgr/models/page.py +32 -0
- tlgr/models/payment.py +172 -0
- tlgr/models/peer.py +400 -0
- tlgr/models/poll.py +119 -0
- tlgr/models/premium.py +161 -0
- tlgr/models/privacy.py +93 -0
- tlgr/models/profile.py +217 -0
- tlgr/models/reaction.py +160 -0
- tlgr/models/resolve.py +175 -0
- tlgr/models/settings.py +103 -0
- tlgr/models/stars.py +101 -0
- tlgr/models/sticker.py +243 -0
- tlgr/models/story.py +467 -0
- tlgr/models/sync.py +105 -0
- tlgr/models/todo.py +36 -0
- tlgr/models/webapp.py +89 -0
- tlgr/ops/__init__.py +63 -0
- tlgr/ops/_admin.py +313 -0
- tlgr/ops/_auth.py +599 -0
- tlgr/ops/_bots.py +586 -0
- tlgr/ops/_calls.py +535 -0
- tlgr/ops/_common.py +160 -0
- tlgr/ops/_layer.py +46 -0
- tlgr/ops/_media.py +592 -0
- tlgr/ops/_params.py +212 -0
- tlgr/ops/_rights.py +402 -0
- tlgr/ops/_send.py +593 -0
- tlgr/ops/_serialize.py +667 -0
- tlgr/ops/_settings.py +306 -0
- tlgr/ops/_spec.py +167 -0
- tlgr/ops/_story.py +743 -0
- tlgr/ops/account.py +2604 -0
- tlgr/ops/agent.py +937 -0
- tlgr/ops/auth.py +1282 -0
- tlgr/ops/bot.py +4880 -0
- tlgr/ops/business.py +1520 -0
- tlgr/ops/call.py +1610 -0
- tlgr/ops/chat.py +4025 -0
- tlgr/ops/chat_admin.py +929 -0
- tlgr/ops/chat_extra.py +1061 -0
- tlgr/ops/chat_invite.py +716 -0
- tlgr/ops/chat_manage.py +1691 -0
- tlgr/ops/chat_member.py +1357 -0
- tlgr/ops/chat_stats.py +902 -0
- tlgr/ops/chat_topic.py +905 -0
- tlgr/ops/conference.py +791 -0
- tlgr/ops/config.py +1698 -0
- tlgr/ops/contact.py +2330 -0
- tlgr/ops/daemon.py +1397 -0
- tlgr/ops/draft.py +299 -0
- tlgr/ops/emoji.py +343 -0
- tlgr/ops/events.py +1327 -0
- tlgr/ops/export.py +596 -0
- tlgr/ops/folder.py +1322 -0
- tlgr/ops/gif.py +522 -0
- tlgr/ops/gift.py +1546 -0
- tlgr/ops/giveaway.py +541 -0
- tlgr/ops/inline.py +773 -0
- tlgr/ops/job.py +799 -0
- tlgr/ops/location.py +917 -0
- tlgr/ops/media.py +4495 -0
- tlgr/ops/message.py +3769 -0
- tlgr/ops/net.py +536 -0
- tlgr/ops/notify.py +840 -0
- tlgr/ops/passport.py +464 -0
- tlgr/ops/payment.py +907 -0
- tlgr/ops/poll.py +1078 -0
- tlgr/ops/premium.py +488 -0
- tlgr/ops/privacy.py +794 -0
- tlgr/ops/profile.py +1481 -0
- tlgr/ops/proxy.py +750 -0
- tlgr/ops/reaction.py +1475 -0
- tlgr/ops/resolve.py +1140 -0
- tlgr/ops/search.py +521 -0
- tlgr/ops/settings.py +1066 -0
- tlgr/ops/stars.py +594 -0
- tlgr/ops/sticker.py +1602 -0
- tlgr/ops/story.py +3216 -0
- tlgr/ops/sync.py +788 -0
- tlgr/ops/todo.py +514 -0
- tlgr/ops/user.py +1406 -0
- tlgr/ops/vc.py +2351 -0
- tlgr/ops/webapp.py +717 -0
- tlgr/ops/webhook.py +418 -0
- tlgr/parity.py +386 -0
- tlgr/processors/__init__.py +125 -0
- tlgr/processors/regex.py +26 -0
- tlgr/processors/text.py +56 -0
- tlgr/registry.py +519 -0
- tlgr/schema.py +173 -0
- tlgr/transport/__init__.py +30 -0
- tlgr/transport/autostart.py +293 -0
- tlgr/transport/client.py +805 -0
- tlgr/transport/ndjson.py +44 -0
- tlgr/version.py +31 -0
- tlgr_cli-2.0.1.dist-info/METADATA +957 -0
- tlgr_cli-2.0.1.dist-info/RECORD +192 -0
- tlgr_cli-2.0.1.dist-info/WHEEL +5 -0
- tlgr_cli-2.0.1.dist-info/entry_points.txt +2 -0
- tlgr_cli-2.0.1.dist-info/licenses/LICENSE +21 -0
- tlgr_cli-2.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,957 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tlgr-cli
|
|
3
|
+
Version: 2.0.1
|
|
4
|
+
Summary: Full Telegram account control CLI — agent-friendly, daemon-based, with webhook event push
|
|
5
|
+
Author: tlgrcli
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/tlgrcli/tlgr
|
|
8
|
+
Project-URL: Repository, https://github.com/tlgrcli/tlgr
|
|
9
|
+
Project-URL: Issues, https://github.com/tlgrcli/tlgr/issues
|
|
10
|
+
Keywords: telegram,cli,automation,telethon,agent,webhook
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Communications :: Chat
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: telethon~=1.44.0
|
|
26
|
+
Requires-Dist: click>=8.0
|
|
27
|
+
Requires-Dist: aiohttp>=3.9
|
|
28
|
+
Requires-Dist: msgspec<1.0,>=0.18
|
|
29
|
+
Requires-Dist: tomli>=2.0; python_version < "3.11"
|
|
30
|
+
Requires-Dist: tomli-w>=1.0
|
|
31
|
+
Requires-Dist: pyyaml>=6.0
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
36
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
37
|
+
Requires-Dist: mypy>=1.11; extra == "dev"
|
|
38
|
+
Provides-Extra: fast
|
|
39
|
+
Requires-Dist: cryptg>=0.4; extra == "fast"
|
|
40
|
+
Provides-Extra: proxy
|
|
41
|
+
Requires-Dist: python-socks[asyncio]>=2.4; extra == "proxy"
|
|
42
|
+
Provides-Extra: media
|
|
43
|
+
Requires-Dist: pillow>=10.0; extra == "media"
|
|
44
|
+
Requires-Dist: hachoir>=3.2; extra == "media"
|
|
45
|
+
Provides-Extra: qr
|
|
46
|
+
Requires-Dist: segno>=1.6; extra == "qr"
|
|
47
|
+
Dynamic: license-file
|
|
48
|
+
|
|
49
|
+
# tlgr
|
|
50
|
+
|
|
51
|
+

|
|
52
|
+
<!-- Created with GitHub Repo Banner by Waren Gonzaga: https://ghrb.waren.build -->
|
|
53
|
+
|
|
54
|
+
Full Telegram account control from the terminal. Agent-friendly, daemon-based, with webhook event push.
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
pipx install tlgr-cli
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The command is `tlgr`; the distribution on PyPI is `tlgr-cli`, because the
|
|
61
|
+
shorter name was taken by an unrelated project. `pipx` is the recommendation
|
|
62
|
+
because tlgr runs a long-lived daemon and wants its own environment;
|
|
63
|
+
`pip install tlgr-cli` into a virtualenv works the same way. To track the
|
|
64
|
+
development tip instead, install from the repository:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
pipx install git+https://github.com/tlgrcli/tlgr.git
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
> **For agents:** logging in is a sequence of ordinary commands — `tlgr auth send-code` then `tlgr auth verify-code` — so only *reading the code* needs a person. Secrets come from `--x-env`/`--x-stdin`/`--x-file`, never argv. See [AGENT.md](AGENT.md) for the full agent reference.
|
|
71
|
+
|
|
72
|
+
> **Coming from tlgr 1.x with a running daemon?** Stop it before you upgrade — two processes on one session file is how an authorization gets revoked. [docs/UPGRADING.md](docs/UPGRADING.md) is the ten-minute cutover, including the six output shapes an agent has to adapt to.
|
|
73
|
+
|
|
74
|
+
## Quickstart
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
tlgr config init # create config files
|
|
78
|
+
tlgr login +15551234567 # authenticate (shortcut for account add)
|
|
79
|
+
tlgr daemon start # start background daemon
|
|
80
|
+
tlgr send @username "Hello from tlgr" # send a message
|
|
81
|
+
tlgr chats --limit 20 # list your chats
|
|
82
|
+
tlgr status # check daemon status
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## CLI
|
|
86
|
+
|
|
87
|
+
Every Telegram operation available as a single command. Three output modes: human-readable tables (default), JSON (`--json`) for agents, and plain TSV (`--plain`) for piping.
|
|
88
|
+
|
|
89
|
+
```mermaid
|
|
90
|
+
flowchart LR
|
|
91
|
+
USER["You / Agent"] --> CLI["tlgr CLI"]
|
|
92
|
+
CLI -->|"direct"| TG["Telegram API"]
|
|
93
|
+
CLI -->|"IPC socket"| DAEMON["tlgr daemon"]
|
|
94
|
+
DAEMON --> TG
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Shortcuts
|
|
98
|
+
|
|
99
|
+
Common operations are available as top-level commands for quick access:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
tlgr send <chat> <text> # message send
|
|
103
|
+
tlgr login <phone> # account add
|
|
104
|
+
tlgr logout <alias> # account remove
|
|
105
|
+
tlgr status # daemon status
|
|
106
|
+
tlgr chats # chat list
|
|
107
|
+
tlgr contacts # contact list
|
|
108
|
+
tlgr dl <chat> <msg_id>... # media download
|
|
109
|
+
tlgr up <chat> <path>... # media upload
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Messages
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
tlgr message send <chat> <text> # --file, --caption, --reply-to, --silent, --parse,
|
|
116
|
+
# --schedule, --topic, --send-as, --split
|
|
117
|
+
tlgr message list <chat> # --limit, --cursor, --all, --since, --until
|
|
118
|
+
tlgr message get <chat> <msg_id> # full metadata
|
|
119
|
+
tlgr message delete <chat> <ids...>
|
|
120
|
+
tlgr message search <chat> <query> # --from, --media-type, --cursor
|
|
121
|
+
tlgr message pin <chat> <msg_id> # and: message unpin
|
|
122
|
+
tlgr message react <chat> <id> <emoji> # alias of `reaction add`, see Reactions
|
|
123
|
+
tlgr message read <chat> # --up-to
|
|
124
|
+
tlgr message edit <chat> <id> <text> # --typing N
|
|
125
|
+
tlgr message forward <from> <ids...> --to <chat>
|
|
126
|
+
tlgr message link <chat> <msg_id> # shareable t.me link
|
|
127
|
+
tlgr message entity list <text> # --parse md: what the formatting actually did
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`message send` supports `--typing N` / `--typing-auto` to show a realistic
|
|
131
|
+
"typing…" indicator before the message lands. Text over 4096 UTF-16 units is
|
|
132
|
+
refused unless you pass `--split`.
|
|
133
|
+
|
|
134
|
+
That is the everyday tenth of the group. It also has `preview`, `compose`,
|
|
135
|
+
`summarize`, `translate`, `transcribe`, `report`, `thread list`, `view get`,
|
|
136
|
+
`read-receipt list`, `scheduled send`, `paid set`, `fact-check set`,
|
|
137
|
+
`dice list`, `effect list`, `game *`, `sponsored *`, `suggested *` and
|
|
138
|
+
`tone *` — 43 operations in all, generated from one registry, with generated
|
|
139
|
+
reference in [`docs/reference/message.md`](docs/reference/message.md).
|
|
140
|
+
|
|
141
|
+
`msg` is an alias for `message` (e.g. `tlgr msg send @user "hello"`).
|
|
142
|
+
|
|
143
|
+
### Polls, reactions, checklists and places
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
tlgr poll create <chat> "Lunch?" Pizza Sushi # --quiz --correct N, --multiple,
|
|
147
|
+
# --public-voters, --duration 2h
|
|
148
|
+
tlgr poll vote <chat> <msg_id> 0 # answers are addressed by index
|
|
149
|
+
tlgr poll get <chat> <msg_id> # results, and why you cannot vote
|
|
150
|
+
tlgr poll close <chat> <msg_id> --yes
|
|
151
|
+
|
|
152
|
+
tlgr reaction add <chat> <msg_id> 👍 # keeps the reactions you already had
|
|
153
|
+
tlgr reaction remove <chat> <msg_id> # all of mine
|
|
154
|
+
tlgr reaction user list <chat> <msg_id> # who reacted, per emoji
|
|
155
|
+
tlgr reaction chat set <chat> --some 👍,❤ # what this chat allows (admin)
|
|
156
|
+
|
|
157
|
+
tlgr todo create <chat> "Release" "tag it" "ship it"
|
|
158
|
+
tlgr todo toggle <chat> <msg_id> --done 1 --undone 2
|
|
159
|
+
|
|
160
|
+
tlgr location send <chat> -- <lat> <lon>
|
|
161
|
+
tlgr location live start <chat> -- <lat> <lon> --period 1h
|
|
162
|
+
tlgr search global "release notes" # every chat, one cursor
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Three things worth knowing before scripting these. A poll answer is an opaque
|
|
166
|
+
identifier on the wire, so tlgr resolves your index against the server's own
|
|
167
|
+
copy — `--shuffle` cannot make index 1 mean two answers. `sendReaction` carries
|
|
168
|
+
your *whole* reaction set, so `reaction add` reads what is there and resends
|
|
169
|
+
it rather than replacing it, and `mine` in the reply is the set afterwards. A
|
|
170
|
+
checklist task id is never renumbered, because completions are keyed by it.
|
|
171
|
+
|
|
172
|
+
Anything that spends Stars — `reaction pay`, `search post` past its free quota
|
|
173
|
+
— has no default amount and refuses to run without an explicit one.
|
|
174
|
+
|
|
175
|
+
Generated reference: [`poll`](docs/reference/poll.md),
|
|
176
|
+
[`reaction`](docs/reference/reaction.md), [`todo`](docs/reference/todo.md),
|
|
177
|
+
[`location`](docs/reference/location.md), [`search`](docs/reference/search.md).
|
|
178
|
+
|
|
179
|
+
### Drafts
|
|
180
|
+
|
|
181
|
+
Prepare a reply without sending it — you send (or discard) it later from any
|
|
182
|
+
Telegram client. The human-in-the-loop primitive for agents.
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
tlgr draft set <chat> <text> # --reply-to, --parse
|
|
186
|
+
tlgr draft clear <chat> # --all --yes to clear every draft
|
|
187
|
+
tlgr draft list # all non-empty drafts across chats
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
`draft set` returns the saved draft, and `draft list` reports marked chat ids
|
|
191
|
+
(`-100…` for channels) with `raw_id` beside them. See
|
|
192
|
+
[`docs/reference/draft.md`](docs/reference/draft.md).
|
|
193
|
+
|
|
194
|
+
### Chats
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
tlgr chat list # --folder, --type, --search, --unread, --pinned, --muted
|
|
198
|
+
tlgr inbox # shortcut: chat list (add --unread)
|
|
199
|
+
tlgr catchup # every unread chat with its recent messages, read-only
|
|
200
|
+
tlgr chat open <chat> # history AND a read receipt; --no-read to peek
|
|
201
|
+
tlgr chat read <chat>... # the receipt without the history; --folder, --from-file
|
|
202
|
+
tlgr chat unread <chat> # the undo for an accidental receipt
|
|
203
|
+
tlgr chat get <chat> # --full for getFullUser/getFullChat/getFullChannel
|
|
204
|
+
tlgr chat posters <chat> # distinct senders + message counts, walked internally
|
|
205
|
+
tlgr chat archive <chat>... [--undo] # one RPC for any number of peers
|
|
206
|
+
tlgr chat mute <chat> --for 8h # or --until, --forever, --off, --stories, --folder
|
|
207
|
+
tlgr chat pin <chat>... [--unpin] # --folder pins inside a chat folder; --order rewrites it
|
|
208
|
+
tlgr chat clear <chat> --yes # history goes, chat stays
|
|
209
|
+
tlgr chat delete <chat> --yes # --for-both, or --for-everyone if you own it
|
|
210
|
+
tlgr chat leave <chat>... --yes # --delete-history, --remove-from-folders
|
|
211
|
+
tlgr chat typing <chat> # --action record-audio, upload-photo, …
|
|
212
|
+
tlgr chat notify set <chat> --silent on
|
|
213
|
+
tlgr chat ttl set <chat> 1d # auto-delete timer; omit the period to read it
|
|
214
|
+
tlgr chat theme set <chat> --emoji 🌷
|
|
215
|
+
tlgr chat wallpaper set <chat> --slug pattern
|
|
216
|
+
tlgr chat badge get --limits # the unread badge, and the chat-list limits behind it
|
|
217
|
+
tlgr chat report <chat> --spam --yes
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Members, admins, invites and topics:
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
tlgr chat member list <chat> --filter admins # `chat members` still works
|
|
224
|
+
tlgr chat member ban <chat> @spammer --purge --report --yes
|
|
225
|
+
tlgr chat member restrict <chat> @noisy --deny send-media --until 7d
|
|
226
|
+
tlgr chat admin promote <chat> @alice --rights ban-users,delete-messages
|
|
227
|
+
tlgr chat permission list --mask member # the canonical right names
|
|
228
|
+
tlgr chat permission set <chat> --deny send-stickers
|
|
229
|
+
tlgr chat invite create <chat> --limit 25 --expires 7d
|
|
230
|
+
tlgr chat request approve <chat> --all --yes
|
|
231
|
+
tlgr chat topic create <chat> Releases # the id `--topic` takes
|
|
232
|
+
tlgr chat setting set <chat> --slow-mode 30s --hidden-members on
|
|
233
|
+
tlgr chat create <name> --type supergroup # --members, --photo, --username
|
|
234
|
+
tlgr chat stats get <channel> --load-graphs
|
|
235
|
+
tlgr boost add <channel>
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
`chat list` returns a page of dialogs whose peer is nested under `chat`;
|
|
239
|
+
`chat catchup` and `chat list` never emit a read receipt, `chat open` does on
|
|
240
|
+
purpose, and `chat unread` restores only your own badge. A member row keeps
|
|
241
|
+
its participant wrapper (status, rank, promoter, both rights masks) and every
|
|
242
|
+
mask is allow-polarity, so `chat permission get` round-trips straight back
|
|
243
|
+
into `chat permission set`. Full reference:
|
|
244
|
+
[`docs/reference/chat.md`](docs/reference/chat.md).
|
|
245
|
+
|
|
246
|
+
### Folders
|
|
247
|
+
|
|
248
|
+
A chat folder is a filter, not a container, so every edit rewrites the whole
|
|
249
|
+
filter in one call — and `--folder <name|id>` works on `chat list`,
|
|
250
|
+
`chat read`, `chat mute`, `chat pin` and `chat badge get`.
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
tlgr folder list --with-counts
|
|
254
|
+
tlgr folder create Work --groups --emoji 💼
|
|
255
|
+
tlgr folder add Work @alice # --pin to pin it inside the folder
|
|
256
|
+
tlgr folder remove Work @alice --exclude
|
|
257
|
+
tlgr folder reorder main Work Family
|
|
258
|
+
tlgr folder join t.me/addlist/SLUG # previews; --chats/--all-chats to actually join
|
|
259
|
+
tlgr folder share set Work --all-eligible
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Full reference: [`docs/reference/folder.md`](docs/reference/folder.md).
|
|
263
|
+
|
|
264
|
+
### Contacts
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
tlgr contact list # --with-status --sort last-seen --export vcard --out FILE
|
|
268
|
+
tlgr contact add <user|+phone> [name] # --first-name --last-name --note --share-phone
|
|
269
|
+
tlgr contact rename <user> # --first-name, --last-name (tags non-contacts too)
|
|
270
|
+
tlgr contact remove <user>... # --phone reaches numbers with no account
|
|
271
|
+
tlgr contact search <query> # --mine-only --global-only --recent
|
|
272
|
+
tlgr contact note set <user> <text> # --clear
|
|
273
|
+
tlgr contact status list # online / last-seen for every contact, in one call
|
|
274
|
+
tlgr contact birthday list
|
|
275
|
+
tlgr contact close-friends list|set
|
|
276
|
+
tlgr contact blocked list|set # --stories for the story blocklist
|
|
277
|
+
tlgr contact top list|set # frequent contacts, by category
|
|
278
|
+
tlgr contact import <file.vcf|csv> # bulk phonebook import
|
|
279
|
+
tlgr contact sync <file> # diff a phonebook against the server (--apply)
|
|
280
|
+
tlgr contact saved list # every number ever uploaded, account or not
|
|
281
|
+
tlgr contact share <user> --to <chat>
|
|
282
|
+
tlgr contact share-phone <user> # irreversible
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
An empty `contact add` by phone is **ambiguous** — the number may have no
|
|
286
|
+
account, or its owner may refuse lookups by phone — and `reason` says so
|
|
287
|
+
rather than the reply claiming "no such user".
|
|
288
|
+
|
|
289
|
+
### Users
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
tlgr user get <user> # --full --translate-bio LANG --from-chat/--from-message
|
|
293
|
+
tlgr user dialog-status <user> # does THIS account have prior history with them?
|
|
294
|
+
tlgr user hide-stories <user>... # v1's spelling of `story hide` (--unhide)
|
|
295
|
+
tlgr user block <user> # --stories --report-spam --delete-history
|
|
296
|
+
tlgr user unblock <user>
|
|
297
|
+
tlgr user can-message <user>... # free | premium | paid (and the Stars price)
|
|
298
|
+
tlgr user chat list <user> # groups you share (--leave-all)
|
|
299
|
+
tlgr user link <user> # --profile --text; `me --token` for a contact token
|
|
300
|
+
tlgr user photo list|set <user>
|
|
301
|
+
tlgr user music list <user>
|
|
302
|
+
tlgr user personal-channel get <user>
|
|
303
|
+
tlgr user birthday set <user> <date>
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
`dialog-status` distinguishes "yes", "definitively no", and "cannot tell"
|
|
307
|
+
(exit 13) instead of guessing. Never infer "no history" from an entity
|
|
308
|
+
resolution error — see AGENT.md for why.
|
|
309
|
+
|
|
310
|
+
`hide-stories` is idempotent: it reads the current flag first and reports
|
|
311
|
+
`already: true` without an RPC, so a bulk pass over hundreds of peers is
|
|
312
|
+
nearly free to repeat.
|
|
313
|
+
|
|
314
|
+
### Resolving references
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
tlgr resolve peer <ref>... # @username | id | +phone | t.me link | me
|
|
318
|
+
tlgr resolve username <name>
|
|
319
|
+
tlgr resolve phone <+number> # --offline formats and validates, no RPC
|
|
320
|
+
tlgr resolve link <url> # classify any t.me / tg:// link (--open)
|
|
321
|
+
tlgr resolve cache get # inspect the per-account peer database
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
`resolve link` never *acts*: it says what a link is and names the command
|
|
325
|
+
that would follow it in `delegated_to`. A phone lookup that comes back empty
|
|
326
|
+
exits 13, never 5 — no account and a privacy refusal are indistinguishable.
|
|
327
|
+
|
|
328
|
+
### Stories
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
tlgr story feed list # the stories bar (--hidden, --unread-only)
|
|
332
|
+
tlgr story list <chat> # active; --profile, --archive, --album ID
|
|
333
|
+
tlgr story get <chat> <id> # --views, --link, --areas-out, --translate
|
|
334
|
+
tlgr story post <file>... # --caption, --privacy, --allow, --exclude,
|
|
335
|
+
# --period, --pin, --album, --area-url, …
|
|
336
|
+
tlgr story read <chat> # clears YOUR ring; --register-view to be seen
|
|
337
|
+
tlgr story react|reply|share <chat> <id>
|
|
338
|
+
tlgr story pin|unpin|hide|unhide <chat> [<id>...]
|
|
339
|
+
tlgr story viewer list <chat> <id> # --contacts, --q, --csv PATH
|
|
340
|
+
tlgr story blocklist set <user>... # "Hide my stories from"
|
|
341
|
+
tlgr story album create|edit|list|delete|reorder <chat> …
|
|
342
|
+
tlgr story can-post | stealth set | search | stats get | export | live start | watch
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
`story read` clears your own unread ring and tells the poster nothing;
|
|
346
|
+
`--register-view` is what puts you in their viewer list, and it is opt-in.
|
|
347
|
+
`--privacy` sets the base audience and `--allow`/`--exclude` layer exceptions
|
|
348
|
+
on top, in that order, so "contacts, except Bob" is expressible.
|
|
349
|
+
|
|
350
|
+
### Media, stickers, GIFs and emoji
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
tlgr media get <chat> <msg_id> # kind, size, duration, ids — no download
|
|
354
|
+
tlgr media download <chat> <msg_id>... # --out-dir, --thumb, --range, --resume,
|
|
355
|
+
# --connections, --verify, --all, --read
|
|
356
|
+
tlgr media upload <chat> <path>... # --as, --caption, --spoiler, --album,
|
|
357
|
+
# --ttl, --no-send, --dedupe, --paid-stars
|
|
358
|
+
tlgr media list <chat> --type photo # the shared-media tabs
|
|
359
|
+
tlgr media search <query> # across every chat
|
|
360
|
+
tlgr media export <chat> # resumable archive with a manifest
|
|
361
|
+
tlgr media transfer list|stop|retry # the Downloads panel
|
|
362
|
+
tlgr media limit get # the server's own limits, never guessed
|
|
363
|
+
|
|
364
|
+
tlgr sticker set list|get|add|remove # install / uninstall a set
|
|
365
|
+
tlgr sticker pack create|add|edit # a pack you own (`emoji set …` too)
|
|
366
|
+
tlgr sticker fave|recent|search
|
|
367
|
+
tlgr gif list|add|remove|search|send
|
|
368
|
+
tlgr emoji get|list|search
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
A file's `file_reference` expires in hours, so every command that touches
|
|
372
|
+
bytes re-fetches its source first; `media file-id get --source` is how a
|
|
373
|
+
stored id is made usable again.
|
|
374
|
+
### Calls and video chats
|
|
375
|
+
|
|
376
|
+
tlgr speaks the **signalling** half of calls and carries no audio or video: it
|
|
377
|
+
rings, answers, hangs up, mutes, moderates, records and observes, and nobody
|
|
378
|
+
can hear it. Every answer says so (`"media": "none"`).
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
tlgr call start @alice # --video, --check (rings nothing), --wait
|
|
382
|
+
tlgr call accept <call> # --ack-only marks it received (busy-lock)
|
|
383
|
+
tlgr call decline <call> # --reason missed|busy, --reply "can't talk"
|
|
384
|
+
tlgr call end <call> # --reason, --duration
|
|
385
|
+
tlgr call log list # the Calls tab; --missed, --with @alice
|
|
386
|
+
tlgr call watch # who is ringing, as NDJSON, for a notifier
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
```bash
|
|
390
|
+
tlgr vc create <chat> --yes # video chat, livestream or --rtmp
|
|
391
|
+
tlgr vc get <chat> # state, recording, limits, stream channels
|
|
392
|
+
tlgr vc participant list <chat> # --raised-hands, --video
|
|
393
|
+
tlgr vc mute <chat> [@alice] # --for-me; `vc unmute` = "allow to speak"
|
|
394
|
+
tlgr vc link <chat> --speaker # invite links; `vc rtmp get` for the key
|
|
395
|
+
tlgr vc watch <chat> # the only way to read the in-call chat
|
|
396
|
+
tlgr vc download <chat> --out live.ogg # record a livestream (it cannot play one)
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
```bash
|
|
400
|
+
tlgr conference create # a t.me/call/<slug> link, no crypto needed
|
|
401
|
+
tlgr conference invite <call> @alice # rings them; falls back to the link
|
|
402
|
+
tlgr conference decline <msg_id> # refuse, or cancel an invite you sent
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
Conferences are end-to-end encrypted. Reading, ringing and revoking are
|
|
406
|
+
complete; **joining**, **removing somebody** and **sending inside** need a
|
|
407
|
+
signed `e2e.chain` block that tlgr cannot build — pass one with `--block` and
|
|
408
|
+
`--public-key`, or the command exits 2 naming what is missing.
|
|
409
|
+
|
|
410
|
+
### Bots, inline mode, mini apps and payments
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
tlgr bot get <bot> # the profile card: commands, menu, flags
|
|
414
|
+
tlgr bot list --owned|--similar-to|--popular-apps|--recent
|
|
415
|
+
tlgr bot start <bot> --param <payload> # /start with a hidden deep-link payload
|
|
416
|
+
tlgr bot command send <bot> start # '@botusername' added in a group
|
|
417
|
+
tlgr bot press <chat> <msg_id> --button 0
|
|
418
|
+
tlgr bot url-auth get|accept|decline # Telegram Login, inspected before granted
|
|
419
|
+
tlgr bot menu|permission|access|preview|affiliate|verification|token …
|
|
420
|
+
|
|
421
|
+
tlgr inline query <bot> <query> # @bot query, the bot's own paging
|
|
422
|
+
tlgr inline send <bot> <q> --chat <c> --pick 0
|
|
423
|
+
tlgr inline search gif|venue|image # the built-in bots, named by the server
|
|
424
|
+
|
|
425
|
+
tlgr webapp get|open|send|invoke|watch # mini apps; `open` prints the URL only
|
|
426
|
+
tlgr payment form get|receipt get|info get|card get
|
|
427
|
+
tlgr payment invoice export|send # asking someone else to pay
|
|
428
|
+
tlgr payment subscription list|set # cancel or resume a Star subscription
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
Three things this group does *not* do, on purpose:
|
|
432
|
+
|
|
433
|
+
- **It never pays.** `sendPaymentForm`, `sendStarsForm`, `validateRequestedInfo`
|
|
434
|
+
and `fulfillStarsSubscription` are absent from the surface, not hidden behind
|
|
435
|
+
a flag. `payment form get` reports `payable_here: false` and says why.
|
|
436
|
+
- **It never opens a browser.** `webapp open` prints the signed mini-app URL,
|
|
437
|
+
which carries your init data and is a credential, not a link.
|
|
438
|
+
- **It never presses a button that discloses something without being told to.**
|
|
439
|
+
A phone number, a location, a chat or a poll each needs its own flag;
|
|
440
|
+
without one tlgr prints what it would send and exits 2.
|
|
441
|
+
|
|
442
|
+
### Profile, privacy and notifications
|
|
443
|
+
|
|
444
|
+
```bash
|
|
445
|
+
tlgr profile get # --no-full skips the userFull round trip
|
|
446
|
+
tlgr profile update # --first-name, --last-name, --bio, --birthday, --channel
|
|
447
|
+
tlgr profile photo set avatar.jpg # --video, --emoji ID, --photo-id ID, --fallback
|
|
448
|
+
tlgr profile username set ada # --check, --on/--off, --order a,b
|
|
449
|
+
tlgr profile status set 5301 # --until +7d, --clear
|
|
450
|
+
tlgr profile color set 5 # --profile, collectible:<slug>
|
|
451
|
+
tlgr profile presence set online # tlgr reports neither unless asked
|
|
452
|
+
tlgr profile link --qr # --collectible for the Fragment record
|
|
453
|
+
|
|
454
|
+
tlgr privacy get [key] # omit for every key
|
|
455
|
+
tlgr privacy set last-seen contacts --add-disallow @nosy
|
|
456
|
+
tlgr privacy global set --hide-read-marks on
|
|
457
|
+
tlgr privacy blocked list|set @spammer # --unblock, --stories
|
|
458
|
+
|
|
459
|
+
tlgr notify get private # or groups|channels|stories|reactions|<chat>
|
|
460
|
+
tlgr notify set private --mute 2h # --unmute, --sound ringtone:ID, --preview off
|
|
461
|
+
tlgr notify exception list|clear
|
|
462
|
+
tlgr notify ringtone list|set chime.ogg
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Settings, business, Premium, Stars and gifts
|
|
466
|
+
|
|
467
|
+
```bash
|
|
468
|
+
tlgr settings get # every cloud key, each with what its setter accepts
|
|
469
|
+
tlgr settings set auto-delete 1w # sensitive-content, top-peers, browser, language…
|
|
470
|
+
tlgr settings theme list|install Nord
|
|
471
|
+
tlgr settings language list
|
|
472
|
+
|
|
473
|
+
tlgr business get # hours, location, intro, greeting, away, links, bots
|
|
474
|
+
tlgr business set --tz Europe/London --open 'mon-fri 09:00-18:00'
|
|
475
|
+
tlgr business reply add hello --text "Hi! I will reply shortly."
|
|
476
|
+
tlgr business bot set @mybot --reply-to --read --new-chats # no --all, by design
|
|
477
|
+
|
|
478
|
+
tlgr premium status | premium feature list --limits
|
|
479
|
+
tlgr stars balance get | stars transaction list --out
|
|
480
|
+
tlgr gift list | gift get msg:120 | gift set msg:120 --pin
|
|
481
|
+
tlgr giveaway get @channel 42 | giveaway code apply <slug>
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
tlgr never spends money: the commands that would need a payment form signed
|
|
485
|
+
report the price and stop.
|
|
486
|
+
|
|
487
|
+
### Accounts
|
|
488
|
+
|
|
489
|
+
```bash
|
|
490
|
+
tlgr account add <phone> # starts the login; prints the verify-code line to run next
|
|
491
|
+
tlgr account add --bot --token-env TLGR_BOT_TOKEN --alias helper
|
|
492
|
+
tlgr account import <file.session> # import an existing Telethon session (no re-auth); --alias
|
|
493
|
+
tlgr account export <alias> --out ./work.string
|
|
494
|
+
tlgr account list # (* = default)
|
|
495
|
+
tlgr account switch <alias>
|
|
496
|
+
tlgr account logout <alias> # revokes the authorization on the server
|
|
497
|
+
tlgr account remove <alias> # local only, unless --logout
|
|
498
|
+
tlgr account rename <old> <new>
|
|
499
|
+
tlgr account info [alias]
|
|
500
|
+
tlgr account check [alias] # authorized / revoked / banned / frozen / offline
|
|
501
|
+
tlgr account sync [alias] # refresh stored profile from live Telegram
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
`info`, `check` and `sync` take the alias positionally, but also honor the
|
|
505
|
+
global `-a/--account` flag; with neither, they fall back to the active
|
|
506
|
+
account. Session files are stored `0600` — they are full account credentials,
|
|
507
|
+
and so is anything `account export` produces, which is why it writes to a
|
|
508
|
+
`0600` file unless `--stdout` says you meant to print it.
|
|
509
|
+
|
|
510
|
+
**`logout` is not `remove`.** `logout` revokes the authorization server-side
|
|
511
|
+
(v1 never did, so a removed account went on showing in every other client's
|
|
512
|
+
Devices list) and keeps the alias so you can log back in; `remove` deletes the
|
|
513
|
+
local record and says, in its answer, that the server-side session is still
|
|
514
|
+
alive unless you passed `--logout`.
|
|
515
|
+
|
|
516
|
+
### Logging in
|
|
517
|
+
|
|
518
|
+
```bash
|
|
519
|
+
tlgr auth send-code <phone> --alias work --api-id 12345 --api-hash-env TLGR_API_HASH
|
|
520
|
+
tlgr auth verify-code <code> --alias work --password-env TLGR_2FA_PASSWORD
|
|
521
|
+
tlgr auth qr --alias work # streams tg://login tokens until one is approved
|
|
522
|
+
tlgr auth recover # forgot the cloud password (recovery email)
|
|
523
|
+
tlgr auth code list # the login code Telegram sent this account (chat 777000)
|
|
524
|
+
tlgr auth tos # read the Terms of Service; --accept is a separate run
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
The pending login lives in the daemon — which owns the session file, so two
|
|
528
|
+
processes never open it at once — and is mirrored to
|
|
529
|
+
`<account>/login-state.json` at `0600`, which is what lets the two steps run
|
|
530
|
+
minutes apart. `auth verify-code` exits 4 when the account has a cloud
|
|
531
|
+
password and none was supplied: add `--password-env` and re-run the same line.
|
|
532
|
+
|
|
533
|
+
### Sessions, passwords and connected websites
|
|
534
|
+
|
|
535
|
+
```bash
|
|
536
|
+
tlgr account session list [--unconfirmed] [--pending-password]
|
|
537
|
+
tlgr account session terminate <hash>... | --all-others [--deny]
|
|
538
|
+
tlgr account session confirm <hash> # "yes, it's me"
|
|
539
|
+
tlgr account session set <hash> --calls off # --secret-chats, --auto-terminate 6m
|
|
540
|
+
tlgr account session accept-qr 'tg://login?token=…' # approve another device
|
|
541
|
+
|
|
542
|
+
tlgr account password get [--verify] # 2FA status; --password-env to reveal the recovery address
|
|
543
|
+
tlgr account password set --new-password-env TLGR_2FA_NEW_PASSWORD --hint "…"
|
|
544
|
+
tlgr account password change --password-env … --new-password-env …
|
|
545
|
+
tlgr account password remove --password-env … --yes
|
|
546
|
+
|
|
547
|
+
tlgr account website list # a *different* list from Devices
|
|
548
|
+
tlgr account website revoke <hash>... [--block-bot]
|
|
549
|
+
tlgr account passkey list # auditable; a CLI can never create one
|
|
550
|
+
tlgr account ttl set 12m # delete my account if I am away this long
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
`account session list` derives two fields you cannot get by hand:
|
|
554
|
+
`deny_deadline` (after it, Telegram auto-confirms an unrecognised login for
|
|
555
|
+
you) and `sensitive_actions_eligible_at` (what `SESSION_TOO_FRESH_X` counts
|
|
556
|
+
down to). `password change` refuses when the account stores Telegram Passport
|
|
557
|
+
documents unless `--keep-passport` acknowledges that they will be lost — the
|
|
558
|
+
secure secret is encrypted under the password and tlgr does not implement the
|
|
559
|
+
KDF that would re-encrypt it.
|
|
560
|
+
|
|
561
|
+
### Daemon
|
|
562
|
+
|
|
563
|
+
```bash
|
|
564
|
+
tlgr daemon start # --foreground, --catch-up/--no-catch-up
|
|
565
|
+
tlgr daemon stop # drains in-flight work rather than killing it
|
|
566
|
+
tlgr daemon status # running/ready/healthy, per-account state and lag
|
|
567
|
+
tlgr daemon restart # --grace 10s
|
|
568
|
+
tlgr daemon reconnect # force a reconnect and a catch-up
|
|
569
|
+
tlgr daemon save-state # flush pts/qts and the entity cache now
|
|
570
|
+
tlgr daemon logs --follow --level warning
|
|
571
|
+
tlgr daemon flood list # rate-limit deadlines this install still owes
|
|
572
|
+
tlgr daemon dead-letter list # events no consumer could be given
|
|
573
|
+
tlgr daemon install # LaunchAgent on macOS, systemd --user on Linux
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
### Watching events
|
|
577
|
+
|
|
578
|
+
```bash
|
|
579
|
+
tlgr watch # v1's default: new messages
|
|
580
|
+
tlgr watch --events all --account all # everything, every connected account
|
|
581
|
+
tlgr watch --events read,message_reactions --chat @alice
|
|
582
|
+
tlgr watch --since 91820 --print-cursor
|
|
583
|
+
tlgr events list --group message # the vocabulary --events accepts
|
|
584
|
+
tlgr events get message_new # payload, source constructors, sequence box
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
Push-driven from the daemon's event bus, not polled: the daemon already holds
|
|
588
|
+
the update socket, so a watcher is a bounded queue on it. 114 event types
|
|
589
|
+
cover every `Update*` constructor the pinned Telethon can parse — a message
|
|
590
|
+
edit, a deletion, a read receipt, a reaction, a typing indicator and every
|
|
591
|
+
service message included. v1's `watch` polled `chat list` and `message list`
|
|
592
|
+
every two seconds and could only report new messages.
|
|
593
|
+
|
|
594
|
+
Frames are NDJSON, one per line: exactly one `meta` first, exactly one `end`
|
|
595
|
+
last, and events, `heartbeat`, `gap` and `lag` in between. A `gap` frame says
|
|
596
|
+
how many events the replay window lost — a number rather than silence.
|
|
597
|
+
`--results-only` prints v1's `{event_type, chat_id, data}` line shape.
|
|
598
|
+
|
|
599
|
+
### Update state
|
|
600
|
+
|
|
601
|
+
```bash
|
|
602
|
+
tlgr sync status --channels # pts/qts/seq, per-channel table, lag
|
|
603
|
+
tlgr sync catch-up # replay what was missed while offline
|
|
604
|
+
tlgr sync difference --chat @news # run getDifference by hand (read-only)
|
|
605
|
+
tlgr sync reset # give up on the gap and re-baseline
|
|
606
|
+
tlgr sync backfill @news --from-id 91800 --to-id 91900
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
`catch-up` replays a gap; `reset` gives up on one. Neither is `chat catchup`,
|
|
610
|
+
which is the unread digest a human reads.
|
|
611
|
+
|
|
612
|
+
### Network and proxies
|
|
613
|
+
|
|
614
|
+
```bash
|
|
615
|
+
tlgr net status # DC, transport, proxy, latency, clock offset
|
|
616
|
+
tlgr net ping --probes 5
|
|
617
|
+
tlgr net dc list --ipv6
|
|
618
|
+
tlgr proxy add 'tg://proxy?server=1.2.3.4&port=443&secret=dd00' --set
|
|
619
|
+
tlgr proxy test --every --reorder
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
SOCKS5, HTTP and MTProxy; `tg://proxy` and `t.me/proxy` links both parsed.
|
|
623
|
+
Credentials live in `~/.tlgr/proxies.json` at mode 0600 and never reach argv
|
|
624
|
+
or a listing. `proxy test` probes through a throwaway in-memory session, so a
|
|
625
|
+
probe can never become the account's update-receiving connection.
|
|
626
|
+
|
|
627
|
+
#### Protocol v2
|
|
628
|
+
|
|
629
|
+
The CLI reaches the daemon over `~/.tlgr/daemon.sock`, created `srw-------`
|
|
630
|
+
with the connecting peer's uid checked on every request — v1 left it
|
|
631
|
+
world-writable with no authentication at all.
|
|
632
|
+
|
|
633
|
+
- **The account is always explicit.** The CLI resolves it (`-a` →
|
|
634
|
+
`TLGR_ACCOUNT` → `[accounts] default` → active alias) and sends it. The
|
|
635
|
+
daemon never picks one: with two accounts configured, v1 used whichever
|
|
636
|
+
alias came first out of a set, so you could send from the wrong identity
|
|
637
|
+
with no signal.
|
|
638
|
+
- **Handshake, and one restart.** A client newer than the running daemon
|
|
639
|
+
restarts it exactly once and says so on stderr; `--no-daemon-restart`
|
|
640
|
+
refuses instead (exit 11). Two `tlgr` commands racing with no daemon
|
|
641
|
+
running produce exactly one daemon.
|
|
642
|
+
- **`status` distinguishes alive from working.** `running` is a live process;
|
|
643
|
+
`ready` is a daemon that can serve; `healthy` is one whose accounts are
|
|
644
|
+
actually working. An account whose connection dropped is `degraded` and its
|
|
645
|
+
requests answer exit 8 with a hint instead of `Cannot send requests while
|
|
646
|
+
disconnected`; a revoked session is `needs_login` and answers exit 4.
|
|
647
|
+
- **A live home is protected.** A tlgr home with a `.production` marker file
|
|
648
|
+
is refused unless `TLGR_ALLOW_PRODUCTION_HOME=1`: two processes sharing one
|
|
649
|
+
home share session files, and Telegram revokes an auth key it sees two
|
|
650
|
+
clients on.
|
|
651
|
+
|
|
652
|
+
### Global Flags
|
|
653
|
+
|
|
654
|
+
```
|
|
655
|
+
--json JSON to stdout (for scripting and agents)
|
|
656
|
+
--plain Stable TSV for piping
|
|
657
|
+
-a, --account TEXT Account alias to use
|
|
658
|
+
--results-only In JSON mode, strip envelope and emit only the primary result
|
|
659
|
+
--select FIELDS In JSON mode, project comma-separated fields (supports dot paths)
|
|
660
|
+
--enable-commands Comma-separated allowlist of enabled commands (sandboxing)
|
|
661
|
+
-n, --dry-run Preview destructive operations without executing
|
|
662
|
+
-y, --force Skip confirmations
|
|
663
|
+
--no-input Never prompt; fail instead (CI/agent mode)
|
|
664
|
+
-v, --verbose Verbose logging to stderr
|
|
665
|
+
--version / --help
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
### Environment Variables
|
|
669
|
+
|
|
670
|
+
All global flags can be set via environment variables:
|
|
671
|
+
|
|
672
|
+
| Variable | Equivalent |
|
|
673
|
+
|----------|------------|
|
|
674
|
+
| `TLGR_JSON=1` | `--json` |
|
|
675
|
+
| `TLGR_PLAIN=1` | `--plain` |
|
|
676
|
+
| `TLGR_ACCOUNT=alias` | `--account alias` |
|
|
677
|
+
| `TLGR_ENABLE_COMMANDS=cmd1,cmd2` | `--enable-commands cmd1,cmd2` |
|
|
678
|
+
| `TLGR_AUTO_JSON=1` | Auto-switch to JSON when stdout is piped (non-TTY) |
|
|
679
|
+
|
|
680
|
+
## Webhook -- Event Push
|
|
681
|
+
|
|
682
|
+
tlgr pushes Telegram events to an external HTTP endpoint in real time. Designed for agentic interfaces like [OpenClaw](https://github.com/openclaw) where an agent receives events and calls `tlgr` CLI commands to act.
|
|
683
|
+
|
|
684
|
+
```mermaid
|
|
685
|
+
flowchart LR
|
|
686
|
+
TG["Telegram"] --> DAEMON["tlgr daemon"]
|
|
687
|
+
DAEMON -->|"POST /hooks/agent"| AGENT["Your Agent"]
|
|
688
|
+
AGENT -->|"tlgr --json message send ..."| CLI["tlgr CLI"]
|
|
689
|
+
CLI --> TG
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
Configure it with `tlgr webhook set`, which validates every event name against
|
|
693
|
+
the taxonomy — a name nobody recognises used to be dropped silently, so the
|
|
694
|
+
webhook delivered nothing and never said why:
|
|
695
|
+
|
|
696
|
+
```bash
|
|
697
|
+
tlgr webhook set --url https://example.com/hooks/agent \
|
|
698
|
+
--events message_new,message_edited,message_deleted \
|
|
699
|
+
--secret-env TLGR_WEBHOOK_SECRET --enabled
|
|
700
|
+
tlgr webhook get # configuration and delivery health; secrets redacted
|
|
701
|
+
tlgr webhook test # one delivery, with the exact headers it sent
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
Or edit `~/.tlgr/webhook.toml` directly. Deliveries carry:
|
|
705
|
+
|
|
706
|
+
| Header | Meaning |
|
|
707
|
+
|---|---|
|
|
708
|
+
| `X-Tlgr-Signature` | `sha256=<hmac of the exact body>` — verify over the bytes you received |
|
|
709
|
+
| `X-Tlgr-Delivery` | unique per attempt; reused on a re-drive, so it is an idempotency key |
|
|
710
|
+
| `X-Tlgr-Seq` | the event's per-account sequence number |
|
|
711
|
+
| `X-Tlgr-Event` | the event type |
|
|
712
|
+
| `X-Tlgr-Account` | the account alias |
|
|
713
|
+
|
|
714
|
+
Events arrive as `{"event": <envelope>, "delivery_id": "..."}`:
|
|
715
|
+
|
|
716
|
+
```json
|
|
717
|
+
{
|
|
718
|
+
"event": {
|
|
719
|
+
"seq": 91824,
|
|
720
|
+
"ts": "2026-09-03T09:14:07Z",
|
|
721
|
+
"account": "main",
|
|
722
|
+
"type": "message_new",
|
|
723
|
+
"payload": { "...": "..." },
|
|
724
|
+
"chat_id": -1001234567890
|
|
725
|
+
},
|
|
726
|
+
"delivery_id": "0f3c…"
|
|
727
|
+
}
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
A delivery that fails every attempt is dead-lettered rather than dropped;
|
|
731
|
+
`tlgr daemon dead-letter list` shows them and `daemon dead-letter send`
|
|
732
|
+
re-drives them.
|
|
733
|
+
|
|
734
|
+
## Gateway -- Background Jobs
|
|
735
|
+
|
|
736
|
+
tlgr also ships with a deterministic, always-on Gateway that runs background jobs on your Telegram account. Define declarative pipelines in `~/.tlgr/jobs.yaml` that automatically react to incoming messages -- auto-reply, auto-forward, filter by chat type, time of day, content, and more.
|
|
737
|
+
|
|
738
|
+
```mermaid
|
|
739
|
+
flowchart LR
|
|
740
|
+
TG["Telegram event"] --> F["Filters"]
|
|
741
|
+
F -->|"passed"| P["Processors"]
|
|
742
|
+
P --> A["Actions"]
|
|
743
|
+
A --> R["reply / forward / ..."]
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
A few examples of what you can do:
|
|
747
|
+
|
|
748
|
+
```yaml
|
|
749
|
+
jobs:
|
|
750
|
+
# Auto-reply to all private messages
|
|
751
|
+
- name: private-bot
|
|
752
|
+
account: main
|
|
753
|
+
filters:
|
|
754
|
+
chat_type: private
|
|
755
|
+
actions:
|
|
756
|
+
- reply: "shut up i'm just a bot!"
|
|
757
|
+
|
|
758
|
+
# Forward breaking news to your archive
|
|
759
|
+
- name: news-forward
|
|
760
|
+
account: main
|
|
761
|
+
filters:
|
|
762
|
+
chat_id: "@raw_feed"
|
|
763
|
+
types: [text, photo]
|
|
764
|
+
contains: [breaking]
|
|
765
|
+
actions:
|
|
766
|
+
- forward:
|
|
767
|
+
to: ["@clean_feed", "@archive"]
|
|
768
|
+
processors: [strip_formatting]
|
|
769
|
+
|
|
770
|
+
# Night-mode auto-reply
|
|
771
|
+
- name: night-mode
|
|
772
|
+
account: main
|
|
773
|
+
filters:
|
|
774
|
+
chat_type: private
|
|
775
|
+
time_of_day: "23:00-07:00"
|
|
776
|
+
actions:
|
|
777
|
+
- reply: "I'm sleeping. Will reply tomorrow."
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
Filters support full AND / OR / NOT composition, 20+ built-in filter types, 7 text processors, and a registry pattern for adding your own.
|
|
781
|
+
|
|
782
|
+
For the full Gateway reference -- filters, processors, actions, composition, extensibility -- see **[Gateway documentation](tlgr/gateway/README.md)**.
|
|
783
|
+
|
|
784
|
+
## Agent / Automation
|
|
785
|
+
|
|
786
|
+
tlgr is designed to be consumed by LLM agents and automation pipelines.
|
|
787
|
+
|
|
788
|
+
### Machine-readable schema
|
|
789
|
+
|
|
790
|
+
```bash
|
|
791
|
+
tlgr schema # full CLI schema as JSON
|
|
792
|
+
tlgr schema message send # schema for a specific command
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
Agents can discover all commands, flags, positionals, types, and defaults
|
|
796
|
+
without parsing `--help`. For commands generated from the operation registry
|
|
797
|
+
the schema also carries JSON Schema (draft 2020-12) for the request *and* the
|
|
798
|
+
response, plus a generated example — so a call can be validated before it is
|
|
799
|
+
made. `tlgr agent whoami --json` reports `output_schema_version: 2`.
|
|
800
|
+
|
|
801
|
+
### Feature parity
|
|
802
|
+
|
|
803
|
+
```bash
|
|
804
|
+
tlgr agent parity # coverage of the pinned Telegram feature catalog
|
|
805
|
+
tlgr agent parity --json --uncovered # every gap, by priority and domain
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
The answer to "can tlgr do X yet" without guessing. 2.0.0 covers 1788 of
|
|
809
|
+
1797 catalogued behaviours and all 178 P0 ones; the nine that remain are
|
|
810
|
+
individually waived and each names the MTProto method this build has no
|
|
811
|
+
request class for. Nothing in the report is hand-maintained — it is computed
|
|
812
|
+
from the registry — and the same report is generated into
|
|
813
|
+
[`docs/reference/PARITY.md`](docs/reference/PARITY.md).
|
|
814
|
+
|
|
815
|
+
### JSON envelope
|
|
816
|
+
|
|
817
|
+
Every command wraps its answer — there is no hand-written command left to
|
|
818
|
+
answer any other way:
|
|
819
|
+
|
|
820
|
+
```json
|
|
821
|
+
{"ok": true, "op": "message.send", "result": {...}, "meta": {"request_id": "...", "elapsed_ms": 42}}
|
|
822
|
+
{"ok": false, "error": {"error": "...", "code": "RATE_LIMITED", "exit_code": 7, "wait_seconds": 30}}
|
|
823
|
+
```
|
|
824
|
+
|
|
825
|
+
`--results-only` prints the inner value in either case, which is v1's shape;
|
|
826
|
+
`--select` projects fields by dot path. Paginated operations return
|
|
827
|
+
`{items, has_more, next_cursor, total}` with an opaque signed cursor.
|
|
828
|
+
|
|
829
|
+
### Stable exit codes
|
|
830
|
+
|
|
831
|
+
```bash
|
|
832
|
+
tlgr exit-codes # print the exit code table
|
|
833
|
+
tlgr --json agent exit-codes # as JSON
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
| Code | Meaning |
|
|
837
|
+
|------|---------|
|
|
838
|
+
| 0 | Success |
|
|
839
|
+
| 1 | Generic failure |
|
|
840
|
+
| 2 | Usage / parse error |
|
|
841
|
+
| 3 | Empty results |
|
|
842
|
+
| 4 | Auth required |
|
|
843
|
+
| 5 | Not found |
|
|
844
|
+
| 6 | Permission denied |
|
|
845
|
+
| 7 | Rate limited |
|
|
846
|
+
| 8 | Retryable error |
|
|
847
|
+
| 10 | Config error |
|
|
848
|
+
| 11 | Daemon error |
|
|
849
|
+
| 12 | IPC error |
|
|
850
|
+
| 13 | Indeterminate (unknown — not a negative) |
|
|
851
|
+
| 130 | Interrupted (SIGINT) |
|
|
852
|
+
|
|
853
|
+
### Command sandboxing
|
|
854
|
+
|
|
855
|
+
Restrict which commands an agent can run:
|
|
856
|
+
|
|
857
|
+
```bash
|
|
858
|
+
tlgr --enable-commands="message,chat,schema" send @user "hi" # allowed
|
|
859
|
+
tlgr --enable-commands="message,chat,schema" account remove foo # blocked (exit 2)
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
Or via environment: `TLGR_ENABLE_COMMANDS=message,chat,schema`.
|
|
863
|
+
|
|
864
|
+
For generated commands the allowlist is matched by canonical operation id and
|
|
865
|
+
enforced **inside the daemon**, so an alias cannot be used to get past it
|
|
866
|
+
(`--enable-commands message.list` permits `tlgr msg list`), and a blocked
|
|
867
|
+
operation exits 6. It is a usability guard, not a sandbox: anything that can
|
|
868
|
+
reach the socket can reach the session. See [SECURITY.md](SECURITY.md).
|
|
869
|
+
|
|
870
|
+
### JSON transforms
|
|
871
|
+
|
|
872
|
+
```bash
|
|
873
|
+
tlgr --json --results-only chat list # strip pagination/envelope, emit only the chat array
|
|
874
|
+
tlgr --json --select "chat.id,unread_count" chat list # project specific fields
|
|
875
|
+
```
|
|
876
|
+
|
|
877
|
+
### Auto-JSON for pipelines
|
|
878
|
+
|
|
879
|
+
Set `TLGR_AUTO_JSON=1` and tlgr automatically outputs JSON whenever stdout is piped (non-TTY), without requiring `--json`.
|
|
880
|
+
|
|
881
|
+
### Error hints
|
|
882
|
+
|
|
883
|
+
Errors include actionable recovery hints:
|
|
884
|
+
|
|
885
|
+
```
|
|
886
|
+
Error: No session found for account 'main'
|
|
887
|
+
Session expired. Run: tlgr account add <phone>
|
|
888
|
+
```
|
|
889
|
+
|
|
890
|
+
## Configuration
|
|
891
|
+
|
|
892
|
+
Config files live in `~/.tlgr/`:
|
|
893
|
+
|
|
894
|
+
| File | Format | Purpose |
|
|
895
|
+
|------|--------|---------|
|
|
896
|
+
| `config.toml` | TOML | App defaults, daemon, accounts |
|
|
897
|
+
| `jobs.yaml` | YAML | Gateway job definitions |
|
|
898
|
+
| `webhook.toml` | TOML | Outbound webhook push |
|
|
899
|
+
|
|
900
|
+
```bash
|
|
901
|
+
tlgr config init # create defaults
|
|
902
|
+
tlgr config validate # check syntax + validate filter/action names
|
|
903
|
+
tlgr config path # print config directory
|
|
904
|
+
tlgr config keys # list all known config keys
|
|
905
|
+
tlgr config list # show current values
|
|
906
|
+
tlgr config get <key> # get a single value
|
|
907
|
+
tlgr config set <key> <value> # set a value
|
|
908
|
+
tlgr config unset <key> # reset to default
|
|
909
|
+
```
|
|
910
|
+
|
|
911
|
+
### config.toml
|
|
912
|
+
|
|
913
|
+
```toml
|
|
914
|
+
[defaults]
|
|
915
|
+
output = "human"
|
|
916
|
+
|
|
917
|
+
[accounts]
|
|
918
|
+
default = "main"
|
|
919
|
+
|
|
920
|
+
[daemon]
|
|
921
|
+
auto_start = true
|
|
922
|
+
log_level = "info"
|
|
923
|
+
```
|
|
924
|
+
|
|
925
|
+
## Multi-Account
|
|
926
|
+
|
|
927
|
+
```bash
|
|
928
|
+
tlgr account add +15551234567 --alias personal # then: tlgr auth verify-code <code> --alias personal
|
|
929
|
+
tlgr account add +15559876543 --alias work
|
|
930
|
+
tlgr -a personal message send @friend "Hi"
|
|
931
|
+
```
|
|
932
|
+
|
|
933
|
+
There is no cap on accounts (official apps stop at three). `tlgr auth code
|
|
934
|
+
list -a personal` reads the login code Telegram delivered to *that* account's
|
|
935
|
+
service chat, which is how a second account can be onboarded without anyone
|
|
936
|
+
reading a phone.
|
|
937
|
+
|
|
938
|
+
To eliminate wrong-account mistakes in scripts and agents, enable strict
|
|
939
|
+
account selection — every command must then carry an explicit `-a <alias>`
|
|
940
|
+
(no default-account fallback; violations exit 2):
|
|
941
|
+
|
|
942
|
+
```bash
|
|
943
|
+
tlgr config set require_account true # or per-invocation: TLGR_REQUIRE_ACCOUNT=1
|
|
944
|
+
```
|
|
945
|
+
|
|
946
|
+
Jobs can reference different accounts:
|
|
947
|
+
|
|
948
|
+
```yaml
|
|
949
|
+
jobs:
|
|
950
|
+
- name: work-forward
|
|
951
|
+
account: work
|
|
952
|
+
# ...
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
## License
|
|
956
|
+
|
|
957
|
+
See [LICENSE](LICENSE) for license details.
|