A macOS Telegram client with a coding agent in the composer.
Kite is a fork of TelegramSwift that adds two things: profiles, which split one account into separate working contexts, and an AI panel that runs a real agent — Codex, Claude, or opencode — against the conversation in front of you.
One Telegram account usually holds several unrelated lives: a job, a side project, family. A profile is a saved slice of that account — a set of chat folders, plus its own agent setup. A fresh install starts with a single profile called Base; add more when you want separate contexts, and delete them when you stop needing them.
The active profile shows at the bottom of the sidebar, and switching is one click:
- Visible chat folders — pick which folders a profile shows. Switching profile changes the chat list, so work chats are not sitting next to family chats.
- Scoped search — global search is restricted to the chats the active profile can see, so results from another context do not leak in.
- Per-profile agent setup — each profile keeps its own agent, model and enabled actions.
Everything lives under Settings → Profiles & Automation.
The panel opens from the ✦ button in the composer, next to emoji and voice:
From there you run an action against the current conversation. The agent reads the chat; it never sends anything. Results land in a review area, and you decide whether to use them.
| Action | What it does |
|---|---|
| Summarize | Condenses the conversation over the selected range |
| Action items | Pulls out commitments and open questions |
| Draft reply | Writes a reply for you to review before sending |
| Polish draft | Rewrites what you have already typed |
| Translate | Translates into a language you pick |
| Voice to text | Transcribes voice messages, optionally fully offline |
| Generate image | Generates an image and shows it inline |
| Ask agent | Anything else, in your own words |
Each action can be switched off in settings, so the panel only shows what you actually use.
Conversation range. Actions default to today. Turn Today off to use a saved range instead — 3, 7 or 30 days.
Inline command. Type @prompt followed by your request straight in the message box and
press Enter — it goes to the agent instead of the chat, and the panel opens with the answer.
The draft is never sent as a message.
While it runs. The panel reports what the agent is doing — thinking, writing, or the name of the tool it called — and a request can be stopped at any point. Requests survive the panel being closed, so you can start something long and come back to the result.
Kite speaks ACP (Agent Client Protocol) over stdio and starts the agent as a child process. Nothing is sent to a Kite-operated server; the agent is whatever you point it at.
| Agent | Command |
|---|---|
| Codex | npx -y @agentclientprotocol/codex-acp |
| Claude | npx -y @zed-industries/claude-code-acp |
| opencode | opencode acp |
| Custom | any ACP-speaking binary |
Models come from the agent, not from a hardcoded list. On connect, Kite asks the agent
what it offers and fills the picker from the answer, so a new model appears without waiting
for a Kite release. Two wire shapes are handled: the models object codex-acp reports, and
the configOptions list opencode uses.
A different model per action. Summarizing every chat with a frontier model is a waste; drafting a careful reply with a small one is a false economy. Set a default, then override it per action.
Saved setups per agent. Switching from Codex to Claude and back does not lose either configuration — command, model and per-action overrides are kept for each.
Point a profile at a folder of Markdown — an Obsidian vault, or any notes directory — and the
agent can cite from it while it works. Retrieval is read-only and runs locally through a
bundled MCP adapter (kite_knowledge_mcp.py). Notes are treated as untrusted quoted data, so
text inside a note cannot redirect the agent.
Voice-to-text can run entirely on your machine, against any OpenAI-compatible transcription endpoint — whisper.cpp, faster-whisper-server, LocalAI and Speaches all expose the same API. Nothing leaves the machine, and it works without Telegram Premium.
Kite does not bundle a speech model and will not download one for you. You run the server; Kite just posts audio to it. With whisper.cpp that is three steps:
1. Install whisper.cpp
brew install whisper-cpp2. Download a model. They are not included with the formula. Pick one by how much accuracy you want to pay for:
mkdir -p ~/.whisper-models
curl -L -o ~/.whisper-models/ggml-base.bin \
https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.bin| Model | Download | Notes |
|---|---|---|
ggml-tiny.bin |
78 MB | Fastest, noticeably rougher |
ggml-base.bin |
148 MB | Good default; fine for voice notes |
ggml-small.bin |
488 MB | Better with accents and noise |
ggml-medium.bin |
1.5 GB | Slower, clearly more accurate |
ggml-large-v3.bin |
3.1 GB | Best, wants an M-series with RAM to spare |
Swap the filename in the curl line for any of these. The .en variants
(ggml-base.en.bin) are English-only and a little sharper at it.
3. Run the server
whisper-server -m ~/.whisper-models/ggml-base.bin \
--host 127.0.0.1 --port 8080 \
--inference-path /v1/audio/transcriptions --convert -l auto--convert lets it accept Telegram's OGG/Opus voice notes, and -l auto detects the
language rather than assuming English. Leave it running in a terminal, or wrap it in a
launchd agent if you want it always available.
Then enable it under Settings → Profiles & Automation → Local transcription and press Check Connection — it tells you straight away whether the server is reachable, rather than leaving you to find out when a voice note fails to transcribe.
Kite builds against your own Telegram API credentials. Get a pair from my.telegram.org → API development tools, then:
git clone --recursive https://github.com/NcitDev/kite.git
cd kite
tools/link_credentials.sh # creates ~/.config/kite/Credentials.swift
$EDITOR ~/.config/kite/Credentials.swift
tools/link_credentials.sh # symlinks it into the build
xcodebuild -workspace Telegram-Mac.xcworkspace -scheme Telegram -configuration Release buildThe real file lives outside the repository and is symlinked in, so git clean -fdx cannot
delete your credentials and the link itself is gitignored — an api_hash cannot be committed
by accident. The build fails without it on purpose: a client shipped on someone else's key
gets that key rate-limited or banned, and the failure lands on whoever installed it.
These values are compiled into the binary and are recoverable from any build with strings,
as they are in every Telegram client. Keeping them out of the repository avoids automated
scraping of public git history; it does not make them secret.
Full prerequisites are in INSTALL.md. To package a distributable build:
tools/package_kite.sh /path/to/Kite.app build/distKite asks for the same permissions as upstream Telegram, and for the same reasons: microphone (voice messages and calls), camera (profile pictures), location (sharing your location), network access, and access to files you pick or download.
Additionally, Kite starts the agent you configure as a child process. That agent runs with your user's privileges and can read the folders you point it at. Only configure agents you trust.
Kite follows the fork requirements upstream sets out, and if you fork Kite you inherit them:
- Get your own API ID. Replace the credentials in
packages/ApiCredentials/Sources/ApiCredentials/Config.swiftwith your own pair from my.telegram.org — the ones in the tree are not yours to ship. - Don't call your fork Telegram, and make sure users understand it is unofficial.
- Don't use Telegram's logo. Kite's mark is a folded kite, not a paper plane, and it is indigo rather than Telegram blue.
- Follow the security guidelines — your users' data and privacy depend on it.
- Publish your code. The GPL requires it.
Kite is a fork of TelegramSwift by overtake, which is the overwhelming majority of the work here. Kite is not affiliated with, endorsed by, or connected to Telegram.
Licensed under the GNU General Public License, version 2.0 — see LICENSE.



