n23eos117 downloadsCapture messages from a Telegram bot in your vault. No server required.
Send yourself a message in Telegram — it appears in your Obsidian daily note.
No server, no VPS, no Docker. Works on desktop and mobile.

#idea to route it to a topic note.Text keeps its Telegram formatting — bold, italic, links, code arrive as Markdown. Photos, voice notes and documents are saved into your vault's attachment folder and embedded in the entry, caption included.
The settings UI is available in English and Russian.
Folder, note name and heading are configurable — or flip one toggle and the plugin writes into the daily note the core Daily Notes plugin owns: its folder, its name format, its template. Delivered message IDs are recorded in the note's frontmatter (tg_ids) — hidden in Reading View, travelling with the note — so two devices syncing one vault never produce duplicates.
Capture is instant; delivery happens while Obsidian is open. The plugin polls Telegram every thirty seconds, and there is no background execution on mobile. If Obsidian is closed, your message waits.
1. Create a bot. Message @BotFather in Telegram: /newbot, answer two prompts (a display name, then a username ending in bot), copy the token it gives you.

2. Connect the plugin. Obsidian → Settings → Vault Telegram Bridge → paste the token → Connect. The same screen sets where messages go (folder, note name, heading) and how each entry looks.

3. Send your new bot a message. That chat is now bound to the plugin; messages from any other chat are ignored.
One line format setting decides everything: {time}, {date} and {text} are replaced, the rest is literal — emoji, bold markers, a - bullet all go in the same field. Entries are separated by a blank line.
✏️ **15:29** an idea on a walk
✏️ **15:30** a longer one
spilling onto a second line
Each entry can be wrapped in nothing, a fenced code block (Markdown is inert there), or a callout (boxed, formatting works):
> [!tip]
> ✏️ **15:29** an idea on a walk
Create ordered rules in Settings → Vault Telegram Bridge → Hashtag routes. A rule maps a Telegram hashtag to a vault-relative note path and, optionally, a different heading:
#idea → Inbox/Ideas.md → ## Ideas
#task → Projects/Tasks/YYYY-MM.md → ## Inbox
The first matching rule wins. Matching is case-insensitive and uses Telegram's hashtag metadata, so text that merely resembles a hashtag is not treated as a command. The matched routing tag is removed from the saved entry; other hashtags and formatting stay intact. Note paths support common multi-character Moment.js date tokens such as YYYY, MM, DD, HH, mm and ss. With no match, the message goes to the normal daily note.
Optional transcription supports Telegram voice messages, audio files and round video notes. Enable it in Settings → Vault Telegram Bridge → Voice transcription, then enter:
https://api.openai.com/v1);whisper-1).Two providers that work out of the box:
| Provider | Base URL | Model | Key |
|---|---|---|---|
| Groq (free tier) | https://api.groq.com/openai/v1 |
whisper-large-v3 |
console.groq.com/keys |
| OpenAI | https://api.openai.com/v1 |
whisper-1 |
platform.openai.com/api-keys |
The model must be a speech-to-text model — a chat model on the same endpoint is rejected by the provider. The Check the connection button under the settings sends a fraction of a second of silence and reports exactly what the provider said, so a wrong URL, key or model is caught before the first real voice note.
The audio file is downloaded from Telegram once, stored in the vault, then sent to {baseUrl}/audio/transcriptions. (Telegram serves voice notes as .oga; the upload is renamed to .ogg, which Whisper hosts accept — the file in your vault keeps its real name.) The transcript is written below the embed. If the transcription provider fails, the attachment is still saved and synchronization continues.
The plugin always uses https://api.telegram.org after you configure a bot token. It calls getMe to verify the token, getUpdates to fetch messages, and getFile plus Telegram's file endpoint when a message has an attachment.
If and only if you enable voice transcription, the plugin also sends voice/audio/video-note bytes to the OpenAI-compatible base URL you configure, using the API key you provide. The request path is /audio/transcriptions; the provider receives the media file and model name. Review that provider's privacy and retention policy before enabling the feature.
All network calls go through Obsidian's requestUrl. There is no telemetry, analytics, crash reporting, remote configuration, self-updating or server operated by this project. The shipped plugin has zero runtime dependencies.
The plugin stores the bot token in plain text in data.json inside your Obsidian config folder. If transcription is enabled, its API key is stored in the same file. A stolen bot token gives an attacker control of the bot — reading messages sent to it, posting as it — and nothing else. Not your chats, not your contacts, not your account. Revoking takes thirty seconds: /revoke to @BotFather. (The plugin's Disconnect button removes the token from this vault but does not disable the bot elsewhere.) Revoke a compromised transcription key with its provider.
If you sync .obsidian/ through git, iCloud or Obsidian Sync, these secrets go with it. The plugin does not put a local passphrase in front of them. If your vault is public, add the plugin's data.json to .gitignore.
Bot usernames are guessable, so the plugin binds itself to the first chat that writes to it and silently ignores every other chat. The binding is visible and resettable in settings.
The plugin will never send messages, set reactions, read chats you did not point it at, collect telemetry, phone home, or update itself.
npm install
npm test # unit tests, no Obsidian runtime needed
npm run typecheck # strict
npm run build # typecheck + lint + bundle to main.js
The build fails if any code imports a Node or Electron API (the plugin must run on mobile), or if the product bundle imports GramJS (account-mode work; used only by the Phase 0 spike under spikes/).
Worth reading before changing anything: MANUAL-TEST-GUIDE — checks that need a human and a real phone.
MIT.
If this project was useful to you, feel free to support further development: