Telegram from your terminal — as you, not a bot.
tgcli is a command-line interface for Telegram that uses your personal account via MTProto 2.0 — the same protocol used by official Telegram apps. Send messages, search conversations, sync history, and download media, all from your terminal.
Inspired by wacli (WhatsApp CLI).
| Tool | Operates as you | Send messages | Local search | Maintained |
|---|---|---|---|---|
| tgcli | Yes | Yes | Yes | Yes |
| tdl | Yes | No | No | Yes |
| telegram-send | No (bot) | Yes | No | No |
| telegram-cli | Yes | Yes | No | No (2016) |
# 1. Install
CGO_ENABLED=1 go install github.com/kaosb/tgcli@latest
# 2. Login (once — you'll be prompted for API credentials and phone)
tgcli login
# 3. Use it
tgcli chat ls
tgcli send text @username "Hello from the terminal!"
tgcli msg search "meeting notes"git clone https://github.com/kaosb/tgcli.git && cd tgcli
make build
# Binary at ./tgcliCGO_ENABLED=1 go install github.com/kaosb/tgcli@latestMake sure $GOPATH/bin is in your PATH:
# Add to ~/.zshrc or ~/.bashrc
export PATH="$HOME/go/bin:$PATH"Download the latest binary from GitHub Releases.
Note: tgcli uses SQLite via CGO (
mattn/go-sqlite3), soCGO_ENABLED=1is required at build time. Pre-built binaries don't need this.
tgcli needs a Telegram API application. Create one at my.telegram.org/apps (any name works) — you'll need the api_id and api_hash.
Then just run:
tgcli loginThe login flow is fully interactive and guides you through each step:
- API credentials — Enter your
app_idandapp_hash(saved automatically for next time) - Phone number — Your number with country code (e.g.
+56912345678) - Verification code — Telegram sends a code to your app (or via SMS)
- 2FA password — Only if you have two-factor authentication enabled
$ tgcli login
Telegram API credentials required (get them at https://my.telegram.org/apps)
App ID: 12345678
App Hash: your_api_hash
Credentials saved to /Users/you/.tgcli/config.json
Phone number (with country code, e.g. +56...): +56912345678
Verification code (check Telegram): 12345
2FA password: ********
Logged in as John Doe (ID: 123456789)
The session persists — you only need to do this once. Credentials are stored in ~/.tgcli/config.json and the session in ~/.tgcli/session.json.
Alternative: You can also set credentials via environment variables
TGCLI_APP_IDandTGCLI_APP_HASH(these take priority over the config file).
tgcli logout # End session and remove local sessiontgcli send text @username "Hello!" # By username
tgcli send text 123456789 "Hello!" # By user ID
tgcli send file @username ./report.pdf # Send a file
tgcli send file @username ./photo.jpg --caption "Check this out"tgcli chat ls # All chats
tgcli chat ls --type private # Only DMs
tgcli chat ls --type group --limit 20 # Groupstgcli msg ls @username # Last 20 messages
tgcli msg ls @username --limit 50 # Last 50
tgcli msg context @username 12345 # Messages around #12345Search uses SQLite FTS5 for instant offline full-text search. Run tgcli sync first to build the local index.
tgcli msg search "meeting notes" # Search all chats
tgcli msg search "budget" --chat @username # Search one chattgcli sync # All chats (recent messages)
tgcli sync --chat @username # Full history for one chattgcli export @username # From Telegram API (JSON)
tgcli export @username --local # From local DB (no connection needed)
tgcli export @username -o backup.json # Save to filetgcli download @username 12345 # Download media from message
tgcli download @username 12345 -o ~/media # Custom output directoryYou can refer to chats in multiple ways:
| Format | Example | Type |
|---|---|---|
@username |
@durov |
Username |
123456789 |
123456789 |
User ID |
-123456789 |
-123456789 |
Group |
-100123456789 |
-100123456789 |
Channel / Supergroup |
+1234567890 |
+56912345678 |
Phone (must be in contacts) |
Every command supports these:
| Flag | Description | Default |
|---|---|---|
--json |
Machine-readable JSON output | false |
--store DIR |
Data directory | ~/.tgcli |
--timeout DUR |
Command timeout | 5m |
tgcli connects to Telegram through gotd/td, a pure-Go MTProto 2.0 implementation. This means:
- You are the sender — messages come from your account, not a bot
- No ban risk — Telegram officially supports third-party clients
- Independent session — works without your phone being online
- Login once — session persists until you revoke it
Messages fetched from the API are cached in a local SQLite database with FTS5 full-text search, enabling instant offline search across your entire history.
All data lives in ~/.tgcli/ (configurable with --store):
| File | What it is |
|---|---|
config.json |
API credentials (app_id, app_hash) — keep this private |
session.json |
MTProto session — keep this private |
tgcli.db |
Local message cache + FTS5 search index |
For CI/CD or scripting, you can pass each credential as a flag. Flags and interactive prompts can be mixed — any flag you provide skips its corresponding prompt:
# Provide phone upfront, enter code interactively
tgcli login --phone "+1234567890"
# Fully non-interactive (e.g. for scripts)
tgcli login --phone "+1234567890" --code "12345" --password "your2fa"Note: The
--codeflag requires you to have already triggered a code (e.g. from a priortgcli loginattempt). For most users, the interactive flow is simpler.
- gotd/td — MTProto 2.0 protocol (pure Go)
- mattn/go-sqlite3 — SQLite with FTS5
- spf13/cobra — CLI framework