telegram-sync-cli · Installs the tg command
A Telegram CLI
for you and your agents.
Search your Telegram messages offline, query them with SQL, read a chat’s history, send text or call any Telegram API method from your shell. tg logs in to your own account and saves your messages to a local SQLite cache. Commands answer in JSON by default.
brew install neoromantic/tap/tgmacOS and Linux. You also need your own Telegram API ID and hash. Setup
Free · Open source · What’s new in 0.5.0
$ tg messages search --query "lisbon" \
| jq -r '.data.results[]
| "\(.chat.title) · \(.text)"'
Ana Ribeiro · Flights to Lisbon are cheaper on the 14th
Tomás Klein · I left the climbing shoes in Lisbon, can you grab them?
Maya Chen · Lisbon or Porto for the offsite?
$ - Search and SQL, offline
A read-only daemon saves your messages to a local cache. Search them or query them with SQL, with no API calls.
- Any Telegram API method
tg sendfor text,tg api <method>for everything else. - Made for agents
Commands print JSON, and errors carry a code. Any agent that can run a shell command can use tg.
Local cache
Search your messages
and query them with SQL.
Each account’s messages go into its own SQLite database in ~/.telegram-sync-cli. Search and SQL read from it, so they work offline and make no API calls.
$ tg sql --output csv --query "
SELECT c.title AS chat,
COUNT(*) AS messages
FROM messages_cache m
JOIN chats_cache c
ON c.chat_id = m.chat_id
WHERE c.type = 'private'
GROUP BY chat
ORDER BY messages DESC"
chat,messages
Ana Ribeiro,3
Maya Chen,2
Tomás Klein,1- Full-text search
- Find a word or a phrase in every cached message, newest first.
- Read-only SQL
tg sqlruns SELECT queries over one account’s cache and returns JSON or CSV. It rejects INSERT, UPDATE, DELETE and schema changes.tg sql print-schemadescribes every table, and--tabledescribes its columns.- Cached reads, or
--fresh tg messages list --chatpages through a chat’s history, newest first. History, contacts, chats and users come from the cache when it has them, and--freshasks Telegram instead.
Sync daemon
The daemon saves your messages
and never sends anything.
Run tg daemon start and leave it running in tmux or as a service. It syncs every account you’re logged in to, reads from Telegram and writes only to your local cache.
- On start
- It loads your chat list, then catches up your private chats and small groups: the newest 100 messages the first time, or everything that arrived while the daemon was stopped. It catches up again after a reconnect.
- While it runs
- Every new message is saved as it arrives, in every chat, including large groups and channels. Edits update the saved copy. A deletion only sets a flag, so
--includeDeletedstill finds the message. Your contact list stays current too. - Older history
- Fetched in the background, page by page, back to each chat’s first message. Large groups and channels get it once you turn them on with
tg chats sync <chat>. - Cache size
- Messages stay. The daemon prunes old API activity, expired rate-limit windows and old sync jobs on a schedule.
tg statusshows each account’s cache size, andtg db vacuumgives free space back to the disk.
tg send · tg api
Send text, or call
any Telegram API method.
Built-in commands cover search, contacts, chats and sending text. For everything else, tg api calls a Telegram API method by name and prints the result as JSON.
$ tg api account.checkUsername \
--username=myuser
{
"success": true,
"data": {
"method": "account.checkUsername",
"result": false
}
}- tg send
- Text to an @username, a user ID, a phone number or
mefor Saved Messages, with--reply-toand--silent. The sent message goes into the cache right away. - tg api <method>
- Arguments are the method’s raw fields: flags such as
--username=myuser, or a--jsonobject for nested ones.
For AI agents
Agents get JSON
and an exit code.
Results go to stdout as JSON. Errors go to stderr as JSON with an error code, and the process exits non-zero. Any agent that can run shell commands can use tg, with no MCP server or plugin.
$ tg me
{
"success": false,
"error": {
"code": "AUTH_REQUIRED",
"message": "No account found. Please log in first with \"tg auth login\"",
"suggestion": "Log in with tg auth login"
}
}
$ echo $?
2- Learn tg before you log in
tg --help,tg --versionandtg sql print-schemaneed no account and no API credentials, so an agent can learn the commands and the cache schema first.- Flood waits
- A command waits out Telegram flood waits of up to 60 seconds. A longer one returns
RATE_LIMITEDwithwait_seconds, on that call and on later calls until it ends. - Read a chat page by page
- Each
tg messages listpage carriesnextBeforeandnextAfter, so an agent can walk a chat.tg messages get --context 5opens a search hit with the messages around it.
Get started
Set it up
in four steps.
Install tg
brew install neoromantic/tap/tgOr with Bun 1.4 or newer:
bun i -g @goodit/telegram-sync-cliAdd your API credentials
export TELEGRAM_API_ID=123456 export TELEGRAM_API_HASH=your_api_hashCreate them at my.telegram.org/apps. Put the exports in your shell profile so the daemon sees them too.
If Telegram is blocked, set
TELEGRAM_PROXYto a SOCKS5, HTTP or MTProxy URL for the CLI and daemon. Proxy setup ↗Log in
tg auth login-qrScan the code in Telegram on your phone: Settings → Devices → Link Desktop Device. Or log in by phone with
tg auth login --phone +15550000000.Start the daemon, then search
tg daemon startLeave it running. In another terminal:
tg messages search --query "lisbon"Search covers what the daemon has saved so far.
tg statusshows its progress, any failed sync jobs and the cache size.
Privacy & data
Your session and cache
stay on your machine.
No telemetry. tg has no analytics or usage reporting. It connects to Telegram directly or through your configured proxy.
Local files. Sessions, caches and settings live in ~/.telegram-sync-cli, or wherever TELEGRAM_SYNC_CLI_DATA_DIR points. tg reads your API ID and hash from the environment.
Deleted messages stay. A message already in your cache stays there after it is deleted in Telegram. Delete the data directory to remove everything.
This website uses cookieless PostHog analytics for page visits and link clicks. Session recording is off. Website analytics are separate from tg and never see your Telegram data.
Questions
Before you log in.
Is this an official Telegram app?
No. It’s an independent open-source client built on mtcute. It logs in as you, with an API ID and hash you create at my.telegram.org/apps.
Can an agent send messages as me?
Yes, if it can run tg send or tg api. The daemon and tg sql never send, edit or delete anything in Telegram. A read-only mode and a chat allowlist are planned (#26).
How do I read one chat’s history?
Run tg messages list --chat @username. It returns the newest messages first, and --before and --after page through the rest. tg messages get with --id and --context 5 shows one message with up to five on each side. Both read the cache first and ask Telegram for what it doesn’t hold.
Does it handle photos and files?
Not yet. tg works with text today. Sending and downloading media is planned (#22).
How is it different from telegram‑mcp?
telegram-mcp is an MCP server with a fixed set of tools that call Telegram live. tg keeps a local cache you can search and query with SQL, and tg api calls any API method. tg is behind on media, waiting for new messages and agent guardrails. The README has the full comparison.
Can I use several accounts?
Yes. Log in to each, then pick one with tg accounts switch or --account. Each account has its own cache, so search and SQL see one account at a time. The daemon syncs every account you’re logged in to, each on its own, so a flood wait in one account doesn’t hold the others.